Skip to content

Local development

The demo runs entirely in the browser. No backend, no environment variables, no external services. The production build adds a server layer; the env-var table below names what it needs.

ToolVersionNotes
Node.js22.xMatches the Vercel runtime.
pnpm10.xThe repo uses pnpm workspaces.
GitAny recentFor cloning.

Install pnpm if you do not have it:

Terminal window
corepack enable
corepack prepare pnpm@latest --activate
Terminal window
git clone https://github.com/bgood11/lending-agent-presenter.git
cd lending-agent-presenter
pnpm install
Terminal window
pnpm dev

Next.js boots on port 3000. Open the surfaces:

SurfaceURL
Marketing landinghttp://localhost:3000
Rep tablethttp://localhost:3000/demo/rep
Customer phonehttp://localhost:3000/demo/customer/demo-token
Admin dashboardhttp://localhost:3000/demo/admin
Admin quote listhttp://localhost:3000/demo/admin/list
Admin quote detailhttp://localhost:3000/demo/admin/quote/solaris-001

The token slot in /demo/customer/[token] accepts any string; the demo does not validate.

The skin switcher (top-right in free-explore mode) writes ?skin=solaris|hayes|bright-lane to the URL and persists in localStorage.

Terminal window
pnpm build
pnpm start

Same routes, optimised bundle. The production build of the demo is what gets deployed to Vercel.

The v1 demo requires no environment variables. Everything is in-bundle.

The planned production build adds the variables below. Names are conventional; any production deploy can substitute its own naming as long as the consuming code is updated to match.

VarSurfaceNotes
DATABASE_URLServerPostgres connection string (Neon or Vercel Postgres)
KV_REST_API_URLServerVercel KV REST endpoint
KV_REST_API_TOKENServerVercel KV token
MAGIC_LINK_SIGNING_KEY_CURRENTServerbase64 of 32 random bytes
MAGIC_LINK_KID_CURRENTServerE.g. 2026-q2
MAGIC_LINK_SIGNING_KEY_PREVIOUSServerPrevious key for rotation overlap
MAGIC_LINK_KID_PREVIOUSServerPrevious kid
MAGIC_LINK_TTL_HOURSServerDefault 336 (14 days)
MAGIC_LINK_BASE_URLServerE.g. https://app.example.com/c/
POSTMARK_SERVER_TOKENServerEmail send
POSTMARK_FROM_EMAILServerE.g. quotes@example.com
BLOB_READ_WRITE_TOKENServerVercel Blob for PDF storage
WEBHOOK_SIGNING_SECRETServerHMAC signing for outgoing audit-event webhooks
AUTH_SECRETServerAuth.js session secret
AUTH_URLServerAuth.js canonical URL
NEXT_PUBLIC_VERCEL_URLClient + serverAuto-set by Vercel; useful in local dev too

Generate a magic-link key:

Terminal window
openssl rand -base64 32

Place env vars in .env.local for local development. .env.local is gitignored.

TaskCommand
Type-check the repopnpm tsc --noEmit
Lintpnpm lint
Formatpnpm fmt (if configured)
Run a single page in isolationUse next dev with --turbo for fastest reloads
Reset the demo stateClear localStorage in DevTools (localStorage.clear())

The scripted walkthrough state is intentionally not persisted: every fresh tab starts at step 0 of the marketing surface. To reset mid-session, click the “Restart walkthrough” link in the footer or run:

useDemoStore.getState().resetWalkthrough();

in the browser DevTools console.

SymptomFix
Geist font not loadingnext/font/google requires network access on first build. Disable proxy and rebuild.
Skin switcher not visibleYou are in scripted mode. Click “Skip walkthrough” to enter free-explore.
Customer phone shows skin’s defaultScenario instead of the in-flight quotelocalStorage was cleared between rep and customer surfaces. Refresh the rep tablet, click Send again.
Admin portal shows zero quotesSkin in URL/state does not match the skin whose fixtures you expect. Switch skin in top-right.