- pnpm dev:local/dev:reset: orchestrate DB container, migrations, seed, and Next.js dev server in one command; Caddy snippet + docs for HTTPS via dev.ginnoir.com - Fix dev login on HTTPS: set both authjs.session-token and __Secure-authjs.session-token so Auth.js finds the session regardless of cookie name resolution - Suppress hydration mismatch on <html> caused by pre-paint script changing data-nav before React hydrates - VAPID startup warning if keys not configured; remove dead NEXT_PUBLIC_VAPID_PUBLIC_KEY var - PushOptIn: hydrate subscription state on mount; reuse existing subscription on iOS to avoid redundant prompts - sendPushToEndpoint: new function to send to a single device endpoint - sendTestNotification: scoped to the calling device's endpoint (ownership-verified) instead of all user subscriptions
6.3 KiB
Dev Login And Local Test Setup
This note tracks the development-only work added to make the app easy to run and test without a live Authentik/OIDC setup.
What Was Added
.envwas created locally with:NEXT_PUBLIC_APP_URL=http://127.0.0.1:3000DATABASE_URL=postgres://famapp:famapp@localhost:5432/famappENABLE_DEV_LOGIN=true- placeholder OIDC values for local-only development
.env.examplenow documents the dev-login variables:ENABLE_DEV_LOGINDEV_LOGIN_EMAILDEV_LOGIN_NAMEDEV_HOUSEHOLD_NAME
src/lib/dev-login-config.tscontains Edge-safe dev-login constants and feature-flag detection.src/lib/dev-login.tscreates a database-backed Auth.js session for a local dev user.src/app/login/page.tsxshows a Dev login button only when:NODE_ENV !== "production"ENABLE_DEV_LOGIN=true
src/middleware.tswas changed to an Edge-safe cookie gate. It no longer imports Auth.js/Drizzle/Postgres into middleware.tests/.auth/is ignored so generated Playwright session state is never committed.- Playwright Chromium was installed locally.
tests/.auth/dev-user.jsonwas generated locally from the Dev login flow.
Related Fixes Found While Enabling Testing
drizzle/0005_auth_schema_repair.sqlwas added to repair local databases that missed the Auth.js schema migration.scripts/seed.tsnow exits cleanly after seeding because imported module default helpers use the shared app database client.src/modules/calendar/server/actions.tsno longer calls.partial()on a refined Zod schema.- Calendar/list E2E locators were tightened so the suite runs against the current UI.
- Calendar/list create buttons no longer depend on
useTransitionpending state for basic enablement.
Current Local Run Procedure
One command starts the database, runs migrations, seeds, and launches the dev server:
pnpm dev:local
The script prints three URLs at startup:
| URL | Use for |
|---|---|
http://localhost:3000 |
Browser on this machine |
http://192.168.1.74:3000 |
Phone on the same WiFi (general UI testing) |
https://dev.ginnoir.com |
Push notifications + PWA install (needs Caddy — see below) |
Then open /login and click Dev login.
HMR and restarts
next dev has hot module replacement — most .ts/.tsx changes apply instantly without a restart.
A full restart (Ctrl+C → pnpm dev:local) is needed for:
.envchangesnext.config.tschanges
Clean slate
To delete all local data and start fresh (e.g. after a destructive schema change):
pnpm dev:reset
HTTPS for push notification and PWA testing (one-time setup)
Service workers and Web Push require HTTPS. The plain LAN address won't work for these. Route through the existing Caddy server on the home server instead — no extra tooling needed.
Step 1 — DHCP reservation
Set a reservation on the router so the dev machine always gets 192.168.1.74.
Step 2 — DNS record
Add a dev.ginnoir.com A record pointing to the same public IP as fam.ginnoir.com.
Step 3 — Windows Firewall
Allow inbound TCP 3000 on the dev machine (run once in an elevated PowerShell):
New-NetFirewallRule -DisplayName "famapp dev" -Direction Inbound `
-Protocol TCP -LocalPort 3000 -Action Allow
Step 4 — Caddy snippet
Paste deploy/Caddyfile.dev.snippet into the home server Caddyfile and reload:
caddy reload --config /path/to/Caddyfile
After this, https://dev.ginnoir.com proxies to the dev machine with a real Let's Encrypt cert.
Current Local E2E Procedure
Generate auth state after starting the app:
New-Item -ItemType Directory -Force tests\.auth | Out-Null
@'
const { chromium } = require('@playwright/test');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('http://127.0.0.1:3000/login');
await page.getByRole('button', { name: 'Dev login' }).click();
await page.waitForURL('http://127.0.0.1:3000/');
await page.context().storageState({ path: 'tests/.auth/dev-user.json' });
await browser.close();
})();
'@ | node -
Run tests:
$env:PLAYWRIGHT_STORAGE_STATE='tests/.auth/dev-user.json'
pnpm test:e2e
After validation, tear down services started for the test run unless you are intentionally keeping the app open:
# Stop a manually started Next dev server if one is still running on port 3000.
Get-NetTCPConnection -LocalPort 3000 -State Listen -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty OwningProcess -Unique |
ForEach-Object { Stop-Process -Id $_ }
# Stop the local database container when the session is finished.
docker compose -f docker-compose.dev.yaml down
Production Removal Plan
Before production deployment, complete the checklist below.
- Set
ENABLE_DEV_LOGIN=falsein production secrets. - Do not copy local
.envto production. - Confirm
deploy/compose.yamlor production env files do not define:ENABLE_DEV_LOGIN=trueDEV_LOGIN_EMAILDEV_LOGIN_NAMEDEV_HOUSEHOLD_NAME
- Verify
/logindoes not render Dev login when built with production env. - Verify direct POSTs to the dev login action fail because
createDevSession()checksNODE_ENV !== "production"andENABLE_DEV_LOGIN=true. - Delete any dev users from the production database if they were accidentally created:
dev@famapp.local- any configured
DEV_LOGIN_EMAIL
- Keep
tests/.auth/ignored and out of production artifacts. - Replace placeholder OIDC variables with real Authentik values:
AUTH_OIDC_ISSUERAUTH_OIDC_CLIENT_IDAUTH_OIDC_CLIENT_SECRET
- Confirm Authentik login succeeds against the production domain.
- Run
pnpm buildwith production-like env before shipping.
Decision For Now
Keep the dev-login code in the repo while active module development is ongoing. It is explicitly gated by environment and avoids requiring Authentik for every local UI/E2E loop.
Before first real production deployment, decide whether to:
- remove the dev-login code entirely, or
- keep it behind the existing production-safe gates for future local development.
Removing it entirely is stricter. Keeping it gated is more convenient. The production blocker is not the presence of the code; it is any production environment that enables it.