Skip to Content

← All archived runs

Run: demo-data-button

run.md

Run: demo-data-button

  • branch: claude/pipeline-demo-data-button-oegmpr
  • pr: #493

01_define/output/spec.md

Spec: Admin demo-data button — populate a tenant with leads across every stage

  • slug: demo-data-button
  • personas: Admin
  • touches: apps/web/app/(app)/admin, apps/web/components/admin, apps/web/lib/actions, packages/services/server
  • complexity: complex

Problem

There is no fast way to fill a tenant with realistic, end-to-end data so the platform can be visualised the way it actually behaves. Demoing the product to prospective vendors, screenshotting the dashboards, and developing UI against the real DB all currently require hand-creating leads one by one — and a single lead only exercises one stage of the service journey. To show the kanban board, lead detail, proposals, quotes, milestones and invoices populated across the whole funnel, you need many leads spread across every stage with their supporting records present.

This directly serves the Build the Bridge initiative (proving the service journey runs end-to-end) and the Q2 objectives around establishing product–market fit and credibility with vendor partners (Objectives 1 and 4) — a one-click populated tenant makes the platform demonstrable and visually complete for sales and internal review. It is explicitly a demo/visualisation aid, not a production data path.

Proposed change

Add a Populate demo data button in the admin section of apps/web (the real, DB-backed platform). Clicking it generates a batch of leads in the admin's current tenant (the active Clerk org), distributed across every lead stage with multiple leads per stage, and creates the supporting records each stage implies so that every view renders realistically:

  • Stages covered (the lead.status workflow): pending, backlog, quotation_process (bid process started), awaiting_confirmation (quote review), work_in_progress, delivered, survey_sent/completed, plus a few qualified_out. Several leads land in each.
  • Full graph per stage — for each lead, create the records appropriate to where it sits:
    • a customer (and, for later stages, an assigned manager and expert);
    • BRD-approved flags / bid-pool flags where the stage requires them;
    • one or more proposals (with expert, price, timeline) once the lead reaches the bid process, in a mix of proposal sub-statuses;
    • a quote (draft/submitted/accepted) for leads at quote review and beyond;
    • milestones in a mix of statuses and invoices in a mix of statuses for work_in_progress/delivered leads;
    • activity log and status-history entries so the activity and progress tabs populate;
    • lead-expert matches so the match list renders.
  • Referenced data — leads point at the tenant's existing reference data (service, industry, product, skills, location). The generator reuses what the tenant already has and creates the demo customers/experts/manager it needs as DB user records (clearly labelled as demo) to attach.
  • requestId is allocated through the tenant's atomic counter, so generated leads get valid sequential request IDs exactly as real leads do.
  • Re-run behaviour: append. Each click adds a fresh batch on top of whatever already exists — no clearing or de-duplication.
  • The button reports a clear result (e.g. counts of leads and supporting records created, or an error) and runs through the standard admin-gated server-action path.

The generation logic lives in @sustentus/services/server (a demo-data service that composes the existing lead/proposal/quote/milestone/invoice/user/activity services), invoked by an admin server action in apps/web. After it runs, the generated leads appear in /service-leads (kanban + table) and each opens to a populated detail view.

Acceptance criteria

  • An admin sees a Populate demo data button in the admin section of apps/web; non-admins cannot reach or invoke it (role-gated like other admin actions).
  • Clicking the button creates leads in the admin's current tenant spread across every lead stage (pending, backlog, quotation_process, awaiting_confirmation, work_in_progress, delivered, survey_sent/completed, qualified_out), with multiple leads in each stage.
  • Each generated lead carries the supporting records its stage implies — a customer (plus manager and expert where applicable), and as appropriate proposals, a quote, milestones, invoices, activity entries, status-history entries, and lead-expert matches — so its /service-leads/[id] detail view renders realistically rather than showing empty sections.
  • After running, the generated leads are visible in the /service-leads kanban board (distributed across the stage columns) and in the table view, with valid sequential requestIds and valid workflow statuses.
  • Supporting records reference real, existing tenant reference data (service/industry/product/ skills/location); demo customers, experts and a manager are created/attached as needed.
  • Re-running the button appends an additional fresh batch without clearing or erroring on the previously generated data.
  • The button surfaces clear feedback on completion (a summary of what was created) and on failure (an error message), without leaving the tenant in a broken state.

Out of scope

  • Any isDemo/production guard or tenant allow-listing — the button runs against the current tenant unconditionally (per decision); choosing a safe tenant is the operator's responsibility.
  • A tenant picker / switcher — generation always targets the current Clerk org. No UI to populate a different tenant.
  • Clearing, resetting, or de-duplicating demo data (re-runs append). Cleanup is a separate concern, covered by the existing snapshot/restore tooling.
  • Provisioning real Clerk-authenticated logins for the generated demo users — they are DB user records for display only, not credentialed accounts.
  • Real attachments/blobs, real BRD chat transcripts, real emails/notifications, or external payment (Stripe/Xero) side effects — generated records use placeholder content where a field is required.
  • The mock apps/dashboards app (it is self-contained on lib/mock/ and unaffected).
  • Tuning the exact per-stage counts into a configurable UI — a sensible fixed spread (multiple per stage) is chosen in Build; making it user-configurable is not required.

Open questions

  • none — exact per-stage volumes, the precise placeholder values for required fields, and the module layout of the demo-data service are Build-time implementation choices that do not change what the feature does.

02_build/output/notes.md

Build notes: demo-data-button

  • commits: feat: demo-data-button — admin button to populate a tenant with leads across every stage

What changed

  • packages/services/src/db/services/demo-data/{index.ts,instance.ts}: new demoDataService.populateDemoLeads(tenantId, createdBy). Generates a fresh batch of demo leads spread across every lead stage (pending, backlog, quotation_process, awaiting_confirmation, work_in_progress, delivered, survey_sent, completed, qualified_out) with multiple leads each, plus the supporting graph per stage:
    • a pool of demo customers (10), experts (6), one CSM "manager" and one vendor, each with a synthetic unique clerkUserId (the (clerkUserId, tenantId) index is not sparse);
    • per lead: status-history chain + a CREATE activity; reference data (service/industry/ product/skills) reused from the tenant when present;
    • bid stage: lead-expert matches + proposals (mix of submitted/draft) + BRD-approved activity;
    • quote review: accepted proposal + rejected proposals + a submitted quote + matches;
    • work-in-progress: accepted proposal + accepted quote + milestones (mixed statuses) + invoices (paid/awaiting payment);
    • delivered/survey/completed: full delivery graph with all milestones done and invoices paid;
    • qualified-out: qualifyOutReason + a QUALIFIED_OUT activity.
    • Writes documents directly via the models (not leadService.create) so it allocates the real per-tenant requestId counter but raises no notifications/emails/external side effects. Re-running appends (new batch tag → unique emails/clerk ids; no deletes).
  • packages/services/src/db/services/index.ts: export demoDataService, DemoDataService, DemoDataResult.
  • apps/web/app/(app)/admin/demo-data/actions.ts: populateDemoData server action — admin-only via resolveActionContext({ allowedRoles: ["admin"] }), calls the service for the current tenant, revalidates /service-leads.
  • apps/web/app/(app)/admin/demo-data/_components/demo-data-button.tsx: client button with a confirm dialog, pending state, success/failure toast, and an inline summary of what was created.
  • apps/web/app/(app)/admin/demo-data/page.tsx: the admin page hosting the button.
  • apps/web/lib/nav.ts: "Demo data" item under the admin Configure section.
  • apps/web/lib/route-policies.ts: /admin/demo-data restricted to admin.

Acceptance criteria status

  • Admin sees a Populate demo data button in apps/web admin; non-admins blocked — nav item under admin Configure, route policy admin only, action gated to allowedRoles: ["admin"].
  • Clicking creates leads across every stage with multiple each — STAGE_PLAN covers all nine lead statuses, ≥2 leads per stage (25 total).
  • Each lead carries the supporting records its stage implies — matches/proposals/quote/ milestones/invoices/activity/status-history wired per stage so detail views render.
  • Visible in /service-leads kanban + table with valid sequential requestIds and valid workflow statuses — statuses are the canonical workflow names; requestId via allocateNextLeadRequestId; list filters by status only.
  • Supporting records reference existing tenant reference data; demo customers/experts/manager created/attached as needed.
  • Re-running appends a fresh batch without clearing or erroring — unique batch tag per run.
  • Clear completion + failure feedback — toast + inline summary on success, error toast + inline message on failure.

Verify result

  • pnpm --filter @sustentus/web typecheck passes locally; @sustentus/services builds (DTS) clean.
  • Format · lint · full typecheck · build run in CI + the Vercel preview; Release reads them back.

Notes for review

  • The button targets the current tenant unconditionally and appends on each run (both per the approved spec — no isDemo guard, no clear/reset). Demo users get synthetic clerkUserIds and are DB records for display only, not real Clerk logins.
  • Reference data is reused if the tenant has it; with none, leads still generate (those refs are optional). For the richest demo, seed reference data first.

03_release/output/changelog.md

Fill a tenant with demo leads in one click

Personas: admin

You can now populate a tenant with example leads spread across every stage of the journey — from new requests through bidding, delivery and completion — so the dashboards, lead board and lead details all show realistic data to explore or demo.

  • Find it under Configure → Demo data in the admin area, then choose Populate demo data.
  • Each run adds a fresh batch with its supporting proposals, quotes, milestones, invoices and activity, so every stage looks the way it does in real use.
  • It's meant for demo and visualisation, so it adds to whatever is already there rather than clearing it — best used on a demo or test tenant.

Live entry: apps/help/app/changelog/2026-06-18-demo-data-button/

03_release/output/investor-update.md

Admins can populate a tenant with a full demo dataset in one click

Who it's for: Admins, and the team running vendor demos What shipped: A one-click admin tool that fills a tenant with leads across every journey stage, plus their proposals, quotes, milestones and invoices. Why it matters: Makes the platform instantly demo-ready for vendor conversations — supporting product–market fit with vendor partners.

Every lead stage is represented with its supporting records, so all dashboards and lead views render realistically.

Dig deeper: <merged-PR URL> · <changelog entry URL>