- Node.js 24.x (repository standard)
- pnpm 10.x
- Docker Desktop
-
Vercel CLI: Install the Vercel CLI globally using
pnpm i -g vercel. -
Login: Run
vercel loginand follow the prompts to authenticate. a. login with GitHub b. use the centralized Vercel account for the project -
Link Project:
vercel link --project findmydoc-portal --scope findmydoc --yes -
Pull for Preview:
vercel pull --environment preview --yes
The repository supports local, hybrid, and cloud operation with the same codebase.
| Mode | Database | Storage | Key Env Signals |
|---|---|---|---|
local |
Local Postgres (Docker) | Local filesystem uploads | DATABASE_URI points to local DB, USE_S3_IN_DEV unset/false |
hybrid |
Remote Postgres (often Supabase) | Local or S3-compatible | DATABASE_URI points to remote DB, optional USE_S3_IN_DEV=true with S3 env |
cloud |
Managed Postgres (often Supabase) | S3-compatible | Production env with managed DB and complete S3 env variables |
If USE_S3_IN_DEV=true, the S3 adapter in src/plugins/index.ts becomes active in development too.
This repo uses a single command to regenerate all generated Payload artifacts (admin import map + TypeScript types):
pnpm generate
Run this after changing Payload config/plugins, collection schemas, or when your branch pulls in Payload-related dependency updates.
Use preview runtime when you want to simulate hosted preview behavior locally:
pnpm dev:redirect-blockerThis command sets:
DEPLOYMENT_ENV=previewNEXT_PUBLIC_DEPLOYMENT_ENV=preview
Result:
- Preview-specific runtime policy applies, including search-index blocking and preview admin recovery.
- Preview Guard login redirects are controlled by the server-side PostHog flag
preview-guard-enabled. - Missing PostHog local flag evaluation keeps Preview Guard disabled because the code default is
false.
See also:
Next.js blocks cross-origin development resources such as /_next/webpack-hmr unless the browser host is allowed. The local dev config automatically allows the machine's active RFC1918 IPv4 LAN addresses, so testing on a phone via http://192.168.x.x:3000 works after the dev server starts.
For VPN or Tailscale hostnames, set your own local value in .env:
NEXT_ALLOWED_DEV_ORIGINS=your-machine.tailnet.ts.netUse hostnames only, without http:// and without :3000. Separate multiple hosts with commas. Keep personal Tailscale or VPN hostnames in .env; .env is ignored by Git, while .env.local is tracked in this repository. Restart pnpm dev after changing the value.
This repository uses an explicit migration-first workflow in every environment.
-
Default local behavior:
Schema push is disabled by default (
PAYLOAD_DB_PUSH=false). -
Required developer flow:
- Create a new migration:
pnpm payload migrate:create <name> - Apply pending migrations locally:
pnpm payload migrate - Verify migration status:
pnpm payload migrate:status - Commit the generated files in
src/migrations/**
- Create a new migration:
-
CI/CD enforcement:
- Build fails if Payload can generate a migration but no migration files were committed.
- Build runs
pnpm payload migrate:statusafter applying migrations. - Preview and Production deployments run migrations as part of
pnpm run ciduring Vercel builds.
-
Optional local experimentation only:
You may temporarily set
PAYLOAD_DB_PUSH=trueon a throwaway local database, but this must not be used for shared or deployed environments.
For the complete release sequence, see Deployment & Migration Runbook.
Use the Developer Dashboard for day-to-day seed execution.
After logging in at http://localhost:3000/admin:
- Navigate to the admin start page and locate the Developer seeding widget.
- Click Seed Baseline to queue the required reference data.
- (Local / non-production only) Click Seed Demo (Reset) to clear demo collections and queue sample content.
- The widget refreshes automatically while a run is active; review the progress bar, job cards, and logs in the widget console.
Notes:
- Baseline seeding never deletes data; repeated runs should show 0 created if nothing changed.
- Demo reset is destructive to demo collections only and is disabled in production.
- Only platform basic users can access seed actions and logs in the widget.
/api/seedPOST is the dashboard entrypoint; it queues jobs instead of running the full seed synchronously.- The dashboard stores only the active
runIdin the browser and restores only active run state from the server after reload. - Terminal runs are cleared from browser storage and are not restored after reload.
- Media-heavy jobs are chunked automatically, so the dashboard can keep polling while the queue advances.
- No external cron worker is needed for the current seed flow.
- Full policy, error handling tiers, and collection ordering: see the Seeding System documentation.
To use findmydoc's Model Context Protocol (MCP) server with developer tools (VS Code, Claude, etc.), you’ll need an MCP API key (platform staff only) and a client configuration.
See: MCP integration
Payload’s REST API is served by the catch‑all route under src/app/(payload)/api/[...slug]/route.ts. Avoid adding per‑collection Next.js routes under /api/<collection> (for example /api/basicUsers), because those shadow the catch‑all route and can cause admin UI relationship lookups to 404.
If you need custom Next.js API endpoints, use non‑conflicting paths (e.g. /api/auth/**, /api/form-bridge/**). Only shadow Payload’s routes with a clear, documented rationale and verify the admin UI still resolves relationship fields correctly.
On first setup, create your initial admin user:
- Visit http://localhost:3000/admin/first-admin
- Fill in your admin credentials
- The page automatically redirects to login once an admin exists
Note: This page is only accessible when no local platform admin users exist in the CMS (
basicUsers).
For local screenshots, manual QA, and ad-hoc browser automation, reuse a stored Playwright session instead of signing in from scratch every time.
Use an existing local or test platform admin or clinic staff account for this workflow. The shared session helper does not provision or clean up auth users.
Record the shared local admin session:
pnpm playwright:session:record -- --persona adminThis command:
- opens a headed browser on
http://localhost:3000/admin/login - waits for you to complete the real login flow manually
- stores the resulting Playwright
storageStateatoutput/playwright/sessions/admin.local.json
Record the shared local clinic session:
pnpm playwright:session:record -- --persona clinicVerify an existing local session before using it in screenshots or scripts:
pnpm playwright:session:check -- --persona admin
pnpm playwright:session:check -- --persona clinicReuse the session in local Playwright contexts with:
const context = await browser.newContext({
storageState: 'output/playwright/sessions/admin.local.json',
})Supported shared admin journeys can capture deterministic checkpoint screenshots directly:
pnpm playwright:journey:capture -- --journey admin.clinics.create-draft --persona adminNotes:
- The session file stays local only;
output/playwright/is already ignored by Git. - This convention is intended for local development only, not for CI fixtures or committed test assets.
- The automated Playwright smoke and regression lanes are separate from this workflow. They log in with fixed
E2E_*credentials, expect those Supabase auth users to exist already, and write their own temporary state files underoutput/playwright/sessions/*.e2e.json. - If the app redirects you back to
/admin/login, the session is no longer valid. Re-runpnpm playwright:session:record -- --persona admin. - Typical invalidation cases are manual logout, expired Supabase sessions, or switching to a different local environment or base URL.
Use Docker Compose to standardize your dev environment:
- Copy environment variables:
cp .env.example .env - Start services:
docker compose up.
For interactive access (e.g., confirming schema changes):
- Payload shell:
docker compose run --rm --service-ports payload - Postgres shell:
docker compose run --rm postgres
Alternatively, use Docker Desktop or docker exec to access the containers and their shells.
- Postgres:
docker exec -it <container_id> psql -U postgres - Payload:
docker exec -it <container_id> sh
Run the docs consistency validator before opening a PR:
pnpm docs:checkWhat it validates:
- broken internal markdown links in
docs/ - referenced
pnpmscripts that do not exist inpackage.json - inline repo path references that no longer exist (placeholder paths are ignored)
CI recommendation:
- add
pnpm docs:checkas a lightweight gate in your docs or PR validation workflow.
