Files
AgendaPro/.superpowers/sdd/task-4-report.md
T
AgendaPro DevandClaude Opus 5 4c19244df9 feat: public landing page with magic login, brand palette and demo build flag
Adds a public funnel landing at `/` and moves the login to `/login`, rebuilt
around the panel's own colors instead of an invented palette.

Landing (`src/components/landing/`, one section per file, no props):
- Seven funnel sections composed by `LandingPage`. The hero's eight swatches are
  literally `PIE_COLORS` from `DashboardPage`, the same hex values the seed hands
  to avatars and services, so "your colors become your numbers" is literal.
- `BrandMark` becomes the single source for the logo, replicating
  `public/favicon.svg`. Blue is the action surface, orange only ever marks.
- `NotebookVisual` is the one deliberate exception to the palette: it is what the
  product replaces.
- Copy drops all system vocabulary; motion comes from `src/lib/motion.ts` with a
  single easing, and reduced-motion resolves `initial` to the final state so a
  never-firing `whileInView` cannot leave a section invisible forever.

Routing and bundle:
- `homePathFor` is the single definition of each role's destination.
- Landing, login, dashboard and calendar load lazily. Eager, the login dragged
  framer-motion (~40 KB gz) into every panel load and the landing downloaded
  recharts + FullCalendar (~187 KB gz) without charting anything. `clsx` is
  pinned to the `react` chunk because Rollup otherwise assigns it to `charts`,
  making the entry import 111 KB gz for a 200-byte utility.

Responsiveness (iPhone/iPad), verified with `npm run audit:responsive`:
- No touch form field below 16px, `dvh` height utilities, safe-area insets, and
  40px touch targets keyed off `pointer: coarse` rather than `sm:`.
- New `.ld-gutter`: `.safe-x` lives outside `@layer` and beats Tailwind's `px-*`,
  so it left the login's side padding at 0 on anything but an iPhone in
  landscape. No overflow check could see it — there was no overflow, just zero
  margin. The audit now guards it with a `gutter` check.
- `shell-height` no longer fires on pages that legitimately scroll; the static
  `raw-viewport-unit` scan covers those instead.

Production build:
- The Dockerfile now sets `VITE_DEMO_UI=1` as a build arg. `DEMO` is a build-time
  constant, so without it Vite eliminated the magic login and the "Ver como…"
  switcher: the deployed landing promised "no registration" and led to an empty
  form. Verified by building both ways and diffing the bundle.
- Service worker cache bumped to v2 so the orphaned pre-landing chunks get purged
  from returning visitors' caches.

Verified: typecheck clean; unit 39/39, e2e 33/33, admin 17/17, booking 12/12,
landing 13/13 (WebKit), PWA passed against the real production build.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-07-28 14:25:58 -06:00

80 lines
5.9 KiB
Markdown

# Task 4 Report
## Files
- Added `pwa-e2e.mjs` with production endpoint, manifest, SPA fallback, Chromium install prompt, iOS instructions, standalone/unsupported states, service-worker readiness/source checks, and real browser `/api/health` request verification.
- Updated `README.md` with local production validation, Android/Chrome installation, iOS Safari instructions, standalone behavior, connectivity expectations, and Coolify HTTPS validation guidance.
## Verification
- `node --check pwa-e2e.mjs`: passed.
- `npm.cmd run typecheck`: passed.
- `npm.cmd run build`: passed; Vite produced the production bundle in `dist/`.
- `npm.cmd run test:pwa`: passed; output `PWA checks passed` against the built production server on port 3000.
- `npm.cmd run audit:visual`: passed; 58 screens/visits, 0 failed loads, 0 horizontal overflow issues. The audit reported 8 console 404 messages while still exiting 0.
- `git diff --check`: passed with no whitespace errors. Git emitted existing LF-to-CRLF working-copy warnings for tracked files.
The first PWA run exposed a test-harness race where the synthetic event could fire before React registered its listener. The harness was corrected to dispatch 100 ms after `load`; the subsequent production run passed.
## Self-review
- Endpoint checks use the configured `PWA_BASE_URL`, defaulting to `http://localhost:3000`.
- Manifest assertions cover standalone display, root start URL/scope, and both required icon sizes.
- Browser contexts are isolated for Chromium prompt, iOS Safari instructions, standalone mode, and unsupported/no-event mode.
- Service-worker readiness has a five-second bound, and the source guard checks cover `/api/` and non-GET requests.
- The browser API check observes a real request and validates its JSON response rather than using a fixture.
- No app authentication, tenant data, API route, database schema, or runtime behavior was changed.
## Concerns
- The visual audit continues to record eight pre-existing 404 console messages on some authenticated/admin visits. They were not introduced by Task 4 and were not changed because the task explicitly limits scope to PWA verification and production documentation.
- The report itself and pre-existing `.superpowers/sdd/*` and `graphify-out/*` changes remain outside the Task 4 commit staging set.
## Review Fixes
- Added `fetchWithTimeout()` using `AbortController` for every direct endpoint/source fetch. The in-page `/api/health` request now uses its own bounded `AbortController` as well.
- Added exact-one accessible-action coverage for the login page, authenticated business shell, and authenticated admin shell. Business/admin flows use the existing demo credentials and a mobile viewport so their compact install controls are visible and accessible.
- Replaced fixed sleeps in standalone/unsupported checks with bounded DOM-state polling for zero matching install actions.
- Replaced iOS body-text checks with visible exact-text locators for `Compartir` and `Añadir a pantalla de inicio`.
- Relaxed service-worker source checks to tolerate whitespace and quote style while still requiring the pathname `/api/` bypass and non-GET guard.
- Tracked all browser contexts and closes them explicitly before closing the browser in `finally`; default UI/navigation timeouts are bounded.
## Review-Fix Verification
- `node --check pwa-e2e.mjs`: passed.
- `npm.cmd run typecheck`: passed.
- `npm.cmd run build`: passed; Vite produced the production bundle in `dist/`.
- `npm.cmd run test:pwa`: passed; output `PWA checks passed` against the built production server on port 3000.
- `npm.cmd run audit:visual`: passed; 58 screens/visits, 0 failed loads, 0 horizontal overflow issues. The audit still reports 8 pre-existing console 404 messages.
- `git diff --check`: passed with no whitespace errors; Git only emitted existing LF-to-CRLF working-copy warnings.
## Review-Fix Self-review
- Direct network operations now have bounded completion, including response-body reads for endpoint/source assertions and the browser-side API response.
- Login, business, and admin each assert one and only one accessible `Instalar AgendaMax` action; the two shell checks exercise the authenticated UI path rather than assuming route markup.
- Negative install-state checks wait on the DOM condition with a timeout and fail non-zero if the condition never becomes true.
- All changes remain in the PWA test harness and this report; application behavior and unrelated tests are unchanged.
## Remaining Concerns
- The visual audit's 8 pre-existing 404 console messages remain outside Task 4 scope. They do not cause failed loads, overflow failures, or a non-zero audit exit.
## Service-worker Behavioral Fix
- Added a reload and `navigator.serviceWorker.controller` gate before behavioral API checks, ensuring requests run through an active, controlling worker.
- While online, the browser now verifies `GET /api/health` returns `200` and a safe invalid `POST /api/auth/login` returns `401`.
- With the Playwright context offline, both API requests must produce bounded network errors rather than cached responses. Connectivity is restored in a `finally` block.
## Service-worker Behavioral Verification
- `npm.cmd run typecheck`: passed.
- `npm.cmd run build`: passed; Vite produced the production bundle in `dist/`.
- `npm.cmd run test:pwa`: passed; output `PWA checks passed` against the built production server on port 3000.
- `git diff --check`: passed with no whitespace errors; Git only emitted existing LF-to-CRLF working-copy warnings.
## Service-worker Behavioral Self-review
- The online assertions validate real statuses (`200` and `401`) before offline mode is enabled, so a cached fixture cannot satisfy the positive path.
- Offline assertions require both requests to reject with a network-error result and do not accept a response status or body.
- The offline state is always reverted in `finally`, and the existing bounded request, navigation, worker-readiness, UI, install-surface, and cleanup checks remain intact.