create-ailk 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -3
- package/component-catalog.md +295 -0
- package/dist/cli.js +92 -16
- package/dist/component-catalog.d.ts +11 -0
- package/dist/component-catalog.js +39 -0
- package/dist/copy.d.ts +7 -0
- package/dist/copy.js +24 -0
- package/dist/derive-architecture.d.ts +13 -0
- package/dist/derive-architecture.js +238 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +19 -2
- package/dist/lib/extract-module-bundle.d.ts +16 -0
- package/dist/lib/extract-module-bundle.js +184 -0
- package/dist/lib/fetch-module.d.ts +55 -0
- package/dist/lib/fetch-module.js +125 -0
- package/dist/lib/module-license-gate.d.ts +48 -0
- package/dist/lib/module-license-gate.js +67 -0
- package/dist/lib/module-tier.d.ts +35 -0
- package/dist/lib/module-tier.js +37 -0
- package/dist/module-architecture.d.ts +175 -0
- package/dist/module-architecture.js +663 -0
- package/dist/parse-args.d.ts +47 -1
- package/dist/parse-args.js +143 -2
- package/dist/programmatic.d.ts +160 -3
- package/dist/programmatic.js +196 -7
- package/dist/surfaces.d.ts +211 -0
- package/dist/surfaces.js +532 -0
- package/dist/sync-routes.d.ts +92 -0
- package/dist/sync-routes.js +350 -0
- package/package.json +22 -14
- package/templates/.claude/rules/architecture.md +6 -2
- package/templates/.claude/skills/README.md +9 -9
- package/templates/.claude/skills/add-schema/SKILL.md +14 -7
- package/templates/.claude/skills/add-schema/references/schema-types.md +109 -6
- package/templates/.claude/skills/provision-config/SKILL.md +1 -1
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +498 -1
- package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +370 -0
- package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +376 -0
- package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +471 -0
- package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +365 -0
- package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +60 -0
- package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +446 -0
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +4 -4
- package/templates/.env.example +126 -2
- package/templates/CLAUDE.md +11 -5
- package/templates/README.md +1 -1
- package/templates/apps/api/.env.example +38 -0
- package/templates/apps/api/CLAUDE.md +75 -1
- package/templates/apps/api/LICENSE +201 -0
- package/templates/apps/api/api/index.ts +6 -141
- package/templates/apps/api/jest.config.cjs +16 -0
- package/templates/apps/api/package.json +22 -6
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +141 -0
- package/templates/apps/api/src/__tests__/server.test.ts +46 -0
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +211 -0
- package/templates/apps/api/src/bin/abandon-sweep.ts +42 -0
- package/templates/apps/api/src/bin/deliverable-resend.ts +144 -0
- package/templates/apps/api/src/bin/deliverable-upload.ts +114 -0
- package/templates/apps/api/src/bin/followup-sweep.ts +44 -0
- package/templates/apps/api/src/bin/listing-csv-sweep.ts +46 -0
- package/templates/apps/api/src/bin/seed-presets.ts +58 -0
- package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +104 -0
- package/templates/apps/api/src/bin/session-retention-sweep.ts +46 -0
- package/templates/apps/api/src/cli.ts +5 -11
- package/templates/apps/api/src/config/index.ts +35 -0
- package/templates/apps/api/src/config/modules.ts +43 -0
- package/templates/apps/api/src/lib/__mocks__/prisma-client.js +11 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +231 -0
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +2 -2
- package/templates/apps/api/src/lib/site.ts +16 -0
- package/templates/apps/api/src/lib/stripe.ts +22 -0
- package/templates/apps/api/src/lib/tenant-db.ts +225 -0
- package/templates/apps/api/src/lib/ws-token.ts +91 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +91 -4
- package/templates/apps/api/src/middleware/auth.ts +43 -8
- package/templates/apps/api/src/middleware/rate-limit.ts +78 -3
- package/templates/apps/api/src/middleware/tenant.ts +99 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +92 -0
- package/templates/apps/api/src/openapi/spec.ts +312 -3
- package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +175 -0
- package/templates/apps/api/src/routes/aeo/index.ts +107 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +5 -2
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +22 -3
- package/templates/apps/api/src/routes/auth/tokens.ts +13 -1
- package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +450 -0
- package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +262 -0
- package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +436 -0
- package/templates/apps/api/src/routes/billing/index.ts +36 -0
- package/templates/apps/api/src/routes/billing/portal.ts +182 -0
- package/templates/apps/api/src/routes/billing/read.ts +75 -0
- package/templates/apps/api/src/routes/billing/usage.ts +153 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +99 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +20 -8
- package/templates/apps/api/src/routes/content/create.ts +1 -0
- package/templates/apps/api/src/routes/content/delete.ts +1 -0
- package/templates/apps/api/src/routes/content/index.ts +42 -6
- package/templates/apps/api/src/routes/content/update.ts +1 -0
- package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +393 -0
- package/templates/apps/api/src/routes/deliverables/index.ts +200 -0
- package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +443 -0
- package/templates/apps/api/src/routes/flow-checkouts/index.ts +82 -0
- package/templates/apps/api/src/routes/flows/README.md +147 -0
- package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +752 -0
- package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +671 -0
- package/templates/apps/api/src/routes/flows/index.ts +202 -0
- package/templates/apps/api/src/routes/flows/recommender.ts +443 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +438 -31
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +10 -10
- package/templates/apps/api/src/routes/leads/index.ts +43 -9
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +547 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +815 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +742 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +424 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +364 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +566 -0
- package/templates/apps/api/src/routes/project-listings/get.ts +70 -0
- package/templates/apps/api/src/routes/project-listings/index.ts +105 -0
- package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
- package/templates/apps/api/src/routes/project-listings/patch-copy.ts +222 -0
- package/templates/apps/api/src/routes/project-listings/patch-draft.ts +97 -0
- package/templates/apps/api/src/routes/project-listings/patch.ts +136 -0
- package/templates/apps/api/src/routes/project-listings/public.ts +52 -0
- package/templates/apps/api/src/routes/project-listings/respond.ts +37 -0
- package/templates/apps/api/src/routes/project-listings/resume-token.ts +22 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +98 -0
- package/templates/apps/api/src/routes/project-listings/submit.ts +122 -0
- package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +490 -0
- package/templates/apps/api/src/routes/schedule/index.ts +249 -0
- package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +385 -0
- package/templates/apps/api/src/routes/slack/actions.ts +177 -0
- package/templates/apps/api/src/routes/slack/index.ts +38 -0
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +16 -6
- package/templates/apps/api/src/routes/test/auth/session.ts +8 -6
- package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +577 -0
- package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +78 -0
- package/templates/apps/api/src/routes/waitlist-experiments/index.ts +41 -0
- package/templates/apps/api/src/routes/waitlist-experiments/list.ts +64 -0
- package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +42 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +84 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +119 -0
- package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +238 -0
- package/templates/apps/api/src/routes/waitlist-signups/index.ts +101 -0
- package/templates/apps/api/src/routes/webhooks/README.md +35 -12
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +315 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +270 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +248 -20
- package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +356 -0
- package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +671 -0
- package/templates/apps/api/src/routes/workspaces/config.ts +125 -0
- package/templates/apps/api/src/routes/workspaces/index.ts +194 -0
- package/templates/apps/api/src/routes/workspaces/sessions.ts +218 -0
- package/templates/apps/api/src/server.ts +293 -7
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +489 -0
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +132 -0
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +523 -0
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +359 -0
- package/templates/apps/api/src/services/__tests__/entitlements.test.ts +142 -0
- package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +425 -0
- package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +2840 -0
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +393 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +8 -8
- package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +560 -0
- package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +406 -0
- package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +290 -0
- package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +736 -0
- package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +340 -0
- package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +983 -0
- package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +278 -0
- package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +71 -0
- package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +379 -0
- package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +941 -0
- package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +588 -0
- package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +768 -0
- package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +1314 -0
- package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +341 -0
- package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +567 -0
- package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +474 -0
- package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +354 -0
- package/templates/apps/api/src/services/abandon-email.ts +307 -0
- package/templates/apps/api/src/services/aeo-score.ts +288 -0
- package/templates/apps/api/src/services/answer-distributions.ts +138 -0
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +523 -0
- package/templates/apps/api/src/services/entitlements.ts +102 -0
- package/templates/apps/api/src/services/flow-aggregate.ts +232 -0
- package/templates/apps/api/src/services/flow-checkouts.ts +123 -0
- package/templates/apps/api/src/services/flow-engine.ts +1278 -0
- package/templates/apps/api/src/services/lead-promotion.ts +176 -0
- package/templates/apps/api/src/services/lead-routing.ts +3 -3
- package/templates/apps/api/src/services/listing-config.ts +102 -0
- package/templates/apps/api/src/services/listing-csv-sweep.ts +455 -0
- package/templates/apps/api/src/services/playbook-compile.ts +398 -0
- package/templates/apps/api/src/services/playbook-render.ts +263 -0
- package/templates/apps/api/src/services/project-listing-decision.ts +490 -0
- package/templates/apps/api/src/services/project-listing-flow.ts +426 -0
- package/templates/apps/api/src/services/project-listing-issue.ts +251 -0
- package/templates/apps/api/src/services/project-listings.ts +1124 -0
- package/templates/apps/api/src/services/recommender-capture.ts +835 -0
- package/templates/apps/api/src/services/scheduling/cal-provider.ts +392 -0
- package/templates/apps/api/src/services/scheduling/index.ts +63 -0
- package/templates/apps/api/src/services/scheduling/types.ts +88 -0
- package/templates/apps/api/src/services/slack-notify.ts +240 -0
- package/templates/apps/api/src/services/tenant-context.ts +451 -0
- package/templates/apps/api/src/services/usage-aggregation.ts +516 -0
- package/templates/apps/api/src/services/usage-credits.ts +340 -0
- package/templates/apps/api/src/services/usage-metering.ts +699 -0
- package/templates/apps/api/src/services/waitlist-dashboard.ts +947 -0
- package/templates/apps/api/src/services/waitlist-experiments.ts +213 -0
- package/templates/apps/api/src/services/waitlist-followup.ts +486 -0
- package/templates/apps/api/src/services/waitlist-scoring.ts +166 -0
- package/templates/apps/api/src/services/waitlist-signups.ts +165 -0
- package/templates/apps/api/src/vercel-handler.ts +165 -0
- package/templates/apps/api/tsconfig.json +0 -12
- package/templates/apps/mcp/CLAUDE.md +19 -9
- package/templates/apps/mcp/LICENSE +201 -0
- package/templates/apps/mcp/__tests__/create_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/delete_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +105 -0
- package/templates/apps/mcp/__tests__/parity.test.ts +70 -6
- package/templates/apps/mcp/__tests__/request_callback.test.ts +4 -4
- package/templates/apps/mcp/__tests__/schedule_tools.test.ts +242 -0
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +4 -4
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +4 -4
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +47 -0
- package/templates/apps/mcp/__tests__/update_page.test.ts +1 -0
- package/templates/apps/mcp/package.json +6 -4
- package/templates/apps/mcp/src/config/modules.ts +37 -0
- package/templates/apps/mcp/src/server.ts +109 -18
- package/templates/apps/mcp/src/tools/capture_lead.ts +1 -1
- package/templates/apps/mcp/src/tools/create_booking.ts +58 -0
- package/templates/apps/mcp/src/tools/create_page.ts +1 -0
- package/templates/apps/mcp/src/tools/delete_page.ts +1 -0
- package/templates/apps/mcp/src/tools/get_event_meta.ts +55 -0
- package/templates/apps/mcp/src/tools/get_flow.ts +61 -0
- package/templates/apps/mcp/src/tools/index.ts +25 -0
- package/templates/apps/mcp/src/tools/list_availability.ts +67 -0
- package/templates/apps/mcp/src/tools/purchase.ts +3 -0
- package/templates/apps/mcp/src/tools/submit_flow_step.ts +83 -0
- package/templates/apps/mcp/src/tools/update_page.ts +1 -0
- package/templates/apps/mcp/tsconfig.json +1 -9
- package/templates/apps/web/.env.example +44 -0
- package/templates/apps/web/CLAUDE.md +28 -0
- package/templates/apps/web/LICENSE +201 -0
- package/templates/apps/web/__tests__/__mocks__/code-highlight.jest-stub.ts +24 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl-server.ts +33 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl.ts +18 -0
- package/templates/apps/web/__tests__/__mocks__/server-only.ts +13 -0
- package/templates/apps/web/__tests__/__mocks__/style-mock.js +4 -0
- package/templates/apps/web/__tests__/__mocks__/vercel-analytics-server.ts +9 -0
- package/templates/apps/web/__tests__/jest-support/import-meta-transformer.cjs +90 -0
- package/templates/apps/web/__tests__/setup.ts +22 -32
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +6 -3
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +8 -2
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +260 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +263 -0
- package/templates/apps/web/app/[locale]/(authed)/account/sign-out-button.tsx +39 -0
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +54 -0
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +96 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +309 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +149 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +273 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/gate.test.tsx +172 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +171 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +179 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +116 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ForbiddenState.tsx +24 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +66 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +61 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +114 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +139 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +85 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +67 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/format.ts +111 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +179 -0
- package/templates/apps/web/app/[locale]/about/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +6 -1
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/careers/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/clients/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +21 -1
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +188 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +242 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +29 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/intake-analytics.test.ts +51 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +39 -15
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +21 -3
- package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +49 -0
- package/templates/apps/web/app/[locale]/contact/intake-script.ts +66 -0
- package/templates/apps/web/app/[locale]/contact/page.tsx +14 -4
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/courses/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +1 -0
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/downloads/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/events/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/faq/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +265 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +445 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +341 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +287 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +302 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +128 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +254 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +144 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +108 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +532 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +121 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +457 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +396 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +114 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +52 -0
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/integrations/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/launch-service/page.tsx +14 -1
- package/templates/apps/web/app/[locale]/layout.tsx +115 -16
- package/templates/apps/web/app/[locale]/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/partners/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/products/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +10 -0
- package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +110 -0
- package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/resources/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +92 -0
- package/templates/apps/web/app/[locale]/schedule/page.tsx +82 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/services/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/sign-in/__tests__/next-path.test.ts +31 -0
- package/templates/apps/web/app/[locale]/sign-in/__tests__/page.test.tsx +152 -0
- package/templates/apps/web/app/[locale]/sign-in/next-path.ts +0 -0
- package/templates/apps/web/app/[locale]/sign-in/page.tsx +83 -0
- package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +123 -0
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/testimonials/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +93 -0
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +48 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/globals.css +35 -0
- package/templates/apps/web/app/llms.txt/route.ts +2 -1
- package/templates/apps/web/app/og/route.tsx +10 -2
- package/templates/apps/web/auth.ts +8 -0
- package/templates/apps/web/components/sign-out-trigger.tsx +42 -0
- package/templates/apps/web/content/en/blog/README.txt +25 -0
- package/templates/apps/web/content/en/docs/index.mdx +28 -0
- package/templates/apps/web/jest.config.cjs +84 -27
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +499 -0
- package/templates/apps/web/lib/account-config.ts +13 -0
- package/templates/apps/web/lib/server-api.ts +85 -0
- package/templates/apps/web/lib/site-brand.tsx +118 -0
- package/templates/apps/web/messages/en.json +275 -7
- package/templates/apps/web/middleware.ts +11 -3
- package/templates/apps/web/next.config.mjs +8 -2
- package/templates/apps/web/package.json +16 -7
- package/templates/apps/web/postcss.config.mjs +23 -0
- package/templates/apps/web/public/.well-known/security.txt +3 -3
- package/templates/apps/web/src/lib/routes.ts +15 -2
- package/templates/apps/web/tsconfig.json +1 -16
- package/templates/content/_site.mdx +24 -25
- package/templates/content/en/AboutPage/about.mdx +24 -14
- package/templates/content/en/ContactPage/contact.mdx +23 -14
- package/templates/content/en/FAQPage/faq.mdx +10 -392
- package/templates/content/en/HomePage/home.mdx +14 -285
- package/templates/database/CHANGELOG.md +382 -0
- package/templates/database/LICENSE +201 -0
- package/templates/database/README.md +3 -1
- package/templates/database/__tests__/flows-listing-diagnostic.test.ts +392 -0
- package/templates/database/__tests__/flows-presets.test.ts +173 -0
- package/templates/database/__tests__/prefixed-ids.db.test.ts +146 -0
- package/templates/database/__tests__/seed.test.ts +88 -0
- package/templates/database/__tests__/user-cascade.test.ts +19 -4
- package/templates/database/auth/schema.prisma +521 -0
- package/templates/database/config/schema.prisma +234 -0
- package/templates/database/content/schema.prisma +263 -0
- package/templates/database/flows/listing-diagnostic.ts +182 -0
- package/templates/database/flows/presets.ts +315 -0
- package/templates/database/inbox/__tests__/schema.test.ts +4 -0
- package/templates/database/inbox/schema.prisma +476 -3
- package/templates/database/jest.config.cjs +8 -0
- package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +201 -0
- package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +67 -0
- package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +46 -0
- package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +25 -0
- package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +49 -0
- package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +197 -0
- package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +32 -0
- package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +22 -0
- package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +151 -0
- package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +223 -0
- package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +22 -0
- package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +32 -0
- package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +40 -0
- package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +4 -0
- package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +2 -0
- package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +2 -0
- package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +29 -0
- package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +6 -0
- package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +39 -0
- package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +24 -0
- package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +3 -0
- package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +33 -0
- package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +30 -0
- package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +47 -0
- package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +16 -0
- package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +47 -0
- package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +10 -0
- package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +26 -0
- package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +90 -0
- package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +174 -0
- package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +14 -0
- package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +25 -0
- package/templates/database/ops/schema.prisma +27 -0
- package/templates/database/package.json +42 -4
- package/templates/database/prisma.config.ts +1 -1
- package/templates/database/schema.prisma +19 -435
- package/templates/database/scripts/db-generate-locked.sh +0 -0
- package/templates/database/seed-test.ts +14 -4
- package/templates/database/seed.ts +148 -0
- package/templates/database/tenancy.ts +45 -0
- package/templates/database/tsconfig.flows.json +15 -0
- package/templates/database/tsconfig.json +7 -1
- package/templates/database/tsconfig.tenancy.json +14 -0
- package/templates/package.json +30 -55
- package/templates/pnpm-workspace.yaml +0 -3
- package/templates/project.yaml +1 -1
- package/templates/tsconfig.json +1 -37
- package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +0 -94
- package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +0 -75
- package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +0 -82
- package/templates/apps/web/__tests__/auth/env-helpers.test.ts +0 -168
- package/templates/apps/web/__tests__/authority-list-routes.test.tsx +0 -208
- package/templates/apps/web/__tests__/better-stack.test.ts +0 -66
- package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +0 -87
- package/templates/apps/web/__tests__/blog-source-populated.test.ts +0 -130
- package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +0 -60
- package/templates/apps/web/__tests__/google-analytics.test.tsx +0 -104
- package/templates/apps/web/__tests__/i18n/middleware.test.ts +0 -119
- package/templates/apps/web/__tests__/i18n/routing.test.ts +0 -114
- package/templates/apps/web/__tests__/i18n/translations.test.ts +0 -191
- package/templates/apps/web/__tests__/json-ld.test.ts +0 -98
- package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +0 -580
- package/templates/apps/web/__tests__/layout-stealth.test.ts +0 -39
- package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +0 -103
- package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +0 -114
- package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +0 -94
- package/templates/apps/web/__tests__/page.test.tsx +0 -230
- package/templates/apps/web/__tests__/products-services-phase1.test.tsx +0 -321
- package/templates/apps/web/__tests__/projects-routes.test.tsx +0 -392
- package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +0 -475
- package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +0 -53
- package/templates/apps/web/__tests__/routes/blog-route.test.tsx +0 -191
- package/templates/apps/web/__tests__/routes/llms-txt.test.ts +0 -123
- package/templates/apps/web/__tests__/routes/robots-txt.test.ts +0 -52
- package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +0 -78
- package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +0 -203
- package/templates/apps/web/__tests__/section-routes.test.tsx +0 -693
- package/templates/apps/web/__tests__/security-headers.test.ts +0 -201
- package/templates/apps/web/__tests__/sentry-config.test.ts +0 -116
- package/templates/apps/web/__tests__/sitemap-locales.test.ts +0 -415
- package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +0 -844
- package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +0 -120
- package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +0 -202
- package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +0 -152
- package/templates/apps/web/content/en/blog/index.mdx +0 -15
- package/templates/apps/web/content/en/blog/launching-ailk.mdx +0 -20
- package/templates/apps/web/content/en/docs/getting-started.mdx +0 -30
- package/templates/content/.gitkeep +0 -0
- package/templates/content/CLAUDE.md +0 -85
- package/templates/content/ar/HomePage/home.mdx +0 -123
- package/templates/content/ar/_site.mdx +0 -35
- package/templates/content/de/_site.mdx +0 -29
- package/templates/content/en/.gitkeep +0 -0
- package/templates/content/en/AboutPage/about.schema.json +0 -82
- package/templates/content/en/BookCall/book-call.mdx +0 -19
- package/templates/content/en/BookCall/book-call.schema.json +0 -121
- package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +0 -20
- package/templates/content/en/CareersList/careers.mdx +0 -24
- package/templates/content/en/CaseStudiesList/case-studies.mdx +0 -22
- package/templates/content/en/CaseStudiesList/showcase.mdx +0 -8
- package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +0 -32
- package/templates/content/en/CaseStudy/schema-builder-migration.mdx +0 -41
- package/templates/content/en/ClientsList/clients.mdx +0 -38
- package/templates/content/en/ContactPage/contact.schema.json +0 -100
- package/templates/content/en/ContactPoint/primary.mdx +0 -14
- package/templates/content/en/Course/aeo-fundamentals.mdx +0 -37
- package/templates/content/en/Course/schema-builder-workshop.mdx +0 -62
- package/templates/content/en/CoursesList/courses.mdx +0 -22
- package/templates/content/en/DownloadsList/downloads.mdx +0 -22
- package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +0 -39
- package/templates/content/en/Event/ailk-launch-day-2026.mdx +0 -35
- package/templates/content/en/EventsList/events.mdx +0 -26
- package/templates/content/en/FAQPage/faq.schema.json +0 -231
- package/templates/content/en/GlossaryList/glossary.mdx +0 -19
- package/templates/content/en/GlossaryList/glossary.schema.json +0 -300
- package/templates/content/en/HomePage/home.schema.json +0 -88
- package/templates/content/en/HomePage/launch-service.mdx +0 -475
- package/templates/content/en/HomePage/launch-service.schema.json +0 -138
- package/templates/content/en/HowTo/add-mdx-content.mdx +0 -38
- package/templates/content/en/HowTo/configure-aeo-scoring.mdx +0 -35
- package/templates/content/en/HowTo/set-up-json-ld.mdx +0 -36
- package/templates/content/en/Integration/github-actions.mdx +0 -31
- package/templates/content/en/Integration/openai-api.mdx +0 -26
- package/templates/content/en/Integration/vercel.mdx +0 -32
- package/templates/content/en/IntegrationsList/integrations.mdx +0 -22
- package/templates/content/en/JobPosting/content-strategist.mdx +0 -46
- package/templates/content/en/JobPosting/developer-advocate.mdx +0 -47
- package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +0 -57
- package/templates/content/en/LandingPage/aeo-audit.mdx +0 -19
- package/templates/content/en/LandingPage/aeo-audit.schema.json +0 -92
- package/templates/content/en/LandingPage/agency-waitlist.mdx +0 -340
- package/templates/content/en/LandingPage/agency-waitlist.schema.json +0 -152
- package/templates/content/en/LandingPage/developers.mdx +0 -19
- package/templates/content/en/LandingPage/developers.schema.json +0 -109
- package/templates/content/en/LandingPage/for-agencies.mdx +0 -390
- package/templates/content/en/LandingPage/for-agencies.schema.json +0 -107
- package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +0 -417
- package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +0 -105
- package/templates/content/en/LandingPage/for-businesses.mdx +0 -19
- package/templates/content/en/LandingPage/for-businesses.schema.json +0 -96
- package/templates/content/en/LandingPage/platform.mdx +0 -369
- package/templates/content/en/LandingPage/platform.schema.json +0 -166
- package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +0 -19
- package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +0 -102
- package/templates/content/en/LandingPage/vs-wordpress.mdx +0 -19
- package/templates/content/en/LandingPage/vs-wordpress.schema.json +0 -53
- package/templates/content/en/NewsletterSignup/newsletter.mdx +0 -236
- package/templates/content/en/NewsletterSignup/newsletter.schema.json +0 -91
- package/templates/content/en/Organization/site-owner.mdx +0 -16
- package/templates/content/en/Partner/prisma.mdx +0 -31
- package/templates/content/en/Partner/supabase.mdx +0 -30
- package/templates/content/en/Partner/vercel.mdx +0 -28
- package/templates/content/en/PartnersList/partners.mdx +0 -22
- package/templates/content/en/Person/founder.mdx +0 -18
- package/templates/content/en/Pricing/pricing.mdx +0 -538
- package/templates/content/en/Pricing/pricing.schema.json +0 -209
- package/templates/content/en/PrivacyPage/privacy.mdx +0 -165
- package/templates/content/en/PrivacyPage/privacy.schema.json +0 -64
- package/templates/content/en/Product/ailk.mdx +0 -19
- package/templates/content/en/Product/ailk.schema.json +0 -94
- package/templates/content/en/Product/api-launch-kit.mdx +0 -26
- package/templates/content/en/Product/launch-kit.mdx +0 -28
- package/templates/content/en/ProductsList/products.mdx +0 -26
- package/templates/content/en/Project/ailk-phase-2.mdx +0 -54
- package/templates/content/en/ProjectsList/projects.mdx +0 -25
- package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +0 -27
- package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +0 -28
- package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +0 -39
- package/templates/content/en/ResourcesHub/resources.mdx +0 -22
- package/templates/content/en/Service/consulting.mdx +0 -22
- package/templates/content/en/Service/implementation.mdx +0 -30
- package/templates/content/en/Service/launch-service.mdx +0 -232
- package/templates/content/en/Service/launch.mdx +0 -228
- package/templates/content/en/ServicesList/services.mdx +0 -84
- package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +0 -44
- package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +0 -47
- package/templates/content/en/SoftwareProduct/ailk-schema.mdx +0 -49
- package/templates/content/en/TeamList/team.mdx +0 -63
- package/templates/content/en/TeamMember/founder.mdx +0 -72
- package/templates/content/en/TermsPage/terms.mdx +0 -19
- package/templates/content/en/TermsPage/terms.schema.json +0 -99
- package/templates/content/en/TestimonialsList/testimonials.mdx +0 -44
- package/templates/content/en/UseCasesList/use-cases.mdx +0 -30
- package/templates/content/en/Whitepaper/ax-first-product-development.mdx +0 -27
- package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +0 -27
- package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +0 -31
- package/templates/content/en-XA/AboutPage/about.mdx +0 -8
- package/templates/content/en-XA/FAQPage/faq.mdx +0 -8
- package/templates/content/en-XA/HomePage/home.mdx +0 -8
- package/templates/content/es/_site.mdx +0 -30
- package/templates/content/fr/_site.mdx +0 -30
- package/templates/content/ja/_site.mdx +0 -30
- package/templates/content/pt-BR/AboutPage/about.mdx +0 -8
- package/templates/content/pt-BR/FAQPage/faq.mdx +0 -8
- package/templates/content/pt-BR/HomePage/home.mdx +0 -23
package/README.md
CHANGED
|
@@ -13,13 +13,134 @@ pnpm install
|
|
|
13
13
|
pnpm dev
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
Compose the site from modules with `--modules` (recognized: `marketing`, `docs`,
|
|
17
|
+
`multi-tenant`; default `marketing`):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm create ailk@latest my-site --modules marketing,docs
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Sync `architecture.yaml` after adding a module
|
|
24
|
+
|
|
25
|
+
When a module is added to an already-scaffolded repo, regenerate its
|
|
26
|
+
`architecture.yaml` in place with `--sync-architecture <csv>` (recognized
|
|
27
|
+
modules are the same set as `--modules`):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# in an already-scaffolded repo (default target: cwd)
|
|
31
|
+
create-ailk --sync-architecture marketing,docs
|
|
32
|
+
# or point at the repo explicitly
|
|
33
|
+
create-ailk --sync-architecture marketing,docs ./my-site
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Sync mode is **data-only and non-destructive**: it rewrites only
|
|
37
|
+
`architecture.yaml` from the module set, re-copies no template tree, and runs
|
|
38
|
+
no install. Because `deriveArchitecture` is byte-deterministic, the synced file
|
|
39
|
+
is identical to a fresh scaffold's for the same module set — the idempotency
|
|
40
|
+
the deferred-sync signal contract depends on.
|
|
41
|
+
|
|
42
|
+
### Sync template routes into an existing site
|
|
43
|
+
|
|
44
|
+
The template is copied once, at scaffold time. When a later release adds a
|
|
45
|
+
route directory (0.14.0 added `/thanks/{slug}` and the flow results page, for
|
|
46
|
+
example), a site scaffolded earlier does not pick it up on its own.
|
|
47
|
+
`sync-routes` reports the route directories a site is missing and, with
|
|
48
|
+
`--apply`, copies exactly those in:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# check — exit 1 if any template route is missing, 0 otherwise (default target: cwd)
|
|
52
|
+
create-ailk sync-routes ./my-site
|
|
53
|
+
# copy the missing route directories in
|
|
54
|
+
create-ailk sync-routes ./my-site --apply
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Check mode lists each missing route with the surface that owns it and the
|
|
58
|
+
release it was added in (`thanks/[slug] (surface: core, added in 0.14.0)`).
|
|
59
|
+
It also lists routes **modified locally** — a route directory the site has,
|
|
60
|
+
whose files differ from what the template would write (an edited, added, or
|
|
61
|
+
deleted file). Modified routes are your edits: they are reported and left
|
|
62
|
+
as-is, they never fail the check, and `--apply` never overwrites them.
|
|
63
|
+
|
|
64
|
+
`--apply` only creates route directories that are absent, through the same
|
|
65
|
+
copier a fresh scaffold uses (so the copied files are byte-identical to a fresh
|
|
66
|
+
scaffold's). It never rewrites or deletes an existing file, never writes
|
|
67
|
+
outside `apps/web/app/[locale]/`, runs no install, and a second run is a
|
|
68
|
+
no-op. `--apply` exits 0 on success.
|
|
69
|
+
|
|
70
|
+
**Scope.** Every core route (`about`, `contact`, `faq`, `thanks/[slug]`,
|
|
71
|
+
`sign-in`) is always checked, and so is the `(authed)` route GROUP —
|
|
72
|
+
`layout.tsx` + `sign-in-gate.tsx`, `account/`, and `waitlist/` — even though
|
|
73
|
+
it is not itself a `--modules`-gated surface (#5014): a fresh scaffold ships
|
|
74
|
+
it unconditionally, the same as core, so `sync-routes` checks it
|
|
75
|
+
unconditionally too. It is reported under its own `authed` identity rather
|
|
76
|
+
than lumped in with `core`, so `sync-routes`'s output distinguishes "always
|
|
77
|
+
present, and this is the sign-in/account shell" from "always present, and
|
|
78
|
+
this is the marketing core." A gateable surface's routes (`blog`, `docs`,
|
|
79
|
+
`flows`, …) are checked only when the site carries that surface; a surface
|
|
80
|
+
gated off at scaffold time is listed as skipped, not missing — its absence is
|
|
81
|
+
deliberate, not drift. Add a surface with `--sync-architecture` and the
|
|
82
|
+
`scaffold-page` skill, not with `sync-routes`.
|
|
83
|
+
|
|
84
|
+
**The lib-and-messages dependency contract (#5014).** Some routes import
|
|
85
|
+
files OUTSIDE their own route directory — `sign-in/page.tsx` imports
|
|
86
|
+
`apps/web/lib/auth-env.ts` and `lib/site-brand.tsx`; the `(authed)` group's
|
|
87
|
+
`layout.tsx` imports `apps/web/auth.ts`; `(authed)/account/page.tsx` imports
|
|
88
|
+
`lib/account-config.ts`, `lib/server-api.ts`, and two files from its
|
|
89
|
+
`(authed)/waitlist` sibling (`components/ForbiddenState.tsx`, `format.ts`).
|
|
90
|
+
Copying a route's directory alone would leave those imports dangling in an
|
|
91
|
+
older consumer that never had them. `ROUTE_DEPENDENCIES` in `src/surfaces.ts`
|
|
92
|
+
declares them per route; `sync-routes` copies each one `--apply` finds
|
|
93
|
+
missing (never overwriting — the same rule routes themselves follow) and
|
|
94
|
+
reports it in check mode under an `Also required` heading. `ROUTE_MESSAGE_NAMESPACES`
|
|
95
|
+
does the same for the i18n namespaces a route's copy needs
|
|
96
|
+
(`signIn`, `account`, `waitlistDashboard.gate`) — but CHECK-ONLY: a
|
|
97
|
+
consumer's `apps/web/messages/<locale>.json` already exists and may carry
|
|
98
|
+
hand-authored translations, so `sync-routes` reports a missing namespace
|
|
99
|
+
rather than attempting to merge JSON keys into it. Adding it is a manual
|
|
100
|
+
step, same as reading any other reported gap.
|
|
101
|
+
|
|
102
|
+
**The manifest.** `ROUTE_SINCE` in `src/surfaces.ts` maps every template route
|
|
103
|
+
directory (relative to `apps/web/app/[locale]`) to the `@working-theory/*`
|
|
104
|
+
fixed-group release line that first shipped it — the version a site pins, so
|
|
105
|
+
the report can say "added in 0.14.0". `create-ailk`'s own version is not the
|
|
106
|
+
axis. `0.0.0` means the route predates the manifest and its first release is
|
|
107
|
+
not recoverable. Surface membership is not in the manifest: it is derived from
|
|
108
|
+
the route-surface registry in the same file.
|
|
109
|
+
|
|
110
|
+
**Maintainer rule:** adding a route directory to the template MUST add a
|
|
111
|
+
`ROUTE_SINCE` entry — `__tests__/sync-routes.test.ts` fails otherwise (and it
|
|
112
|
+
fails on a stale entry for a route the template no longer ships).
|
|
113
|
+
|
|
16
114
|
## What it does
|
|
17
115
|
|
|
18
116
|
1. Validates the target directory does not exist OR is empty.
|
|
19
117
|
2. Copies the curated template tree (`apps/{web,api,mcp}` + `database/` + `content/` + root config files) from the package's `templates/` directory.
|
|
20
118
|
3. Substitutes `workspace:*` references in every `package.json` with the matching `@working-theory/*` semver from npm — versions are pinned at npm-publish time.
|
|
21
119
|
4. Substitutes `{{PROJECT_NAME}}`, `{{COMPANY_NAME}}`, `{{COMPANY_DOMAIN}}` markers in `templates/README.md` from the target directory name (and CLI flags / interactive prompts in future versions).
|
|
22
|
-
5.
|
|
120
|
+
5. Derives and writes `architecture.yaml` (the site's code-boundary config) from the selected module set — see below.
|
|
121
|
+
6. Prints next steps: `cd <dir> && pnpm install && pnpm dev`.
|
|
122
|
+
|
|
123
|
+
## `architecture.yaml` is derived from the module set
|
|
124
|
+
|
|
125
|
+
The scaffolded site's `architecture.yaml` (the apps/packages/namespaces the
|
|
126
|
+
architecture linter walks + the import rules it enforces) is **derived from the
|
|
127
|
+
selected `--modules`**, not copied from a fixed template. The module set is the
|
|
128
|
+
single source of truth for the site's code-architecture boundaries:
|
|
129
|
+
|
|
130
|
+
- A **module → architecture-slice registry** (`src/module-architecture.ts`) maps
|
|
131
|
+
each recognized module to the boundary fragment it contributes.
|
|
132
|
+
- **`deriveArchitecture(modules)`** (`src/derive-architecture.ts`, also exported
|
|
133
|
+
from the package index) composes a module-independent base with the selected
|
|
134
|
+
slices into one deterministic document. Same module set → byte-identical
|
|
135
|
+
output.
|
|
136
|
+
- The scaffolder writes the derived file at the target root, satisfying the
|
|
137
|
+
scaffolded `project.yaml`'s `architecture_rules: architecture.yaml` reference.
|
|
138
|
+
|
|
139
|
+
**Sync on module-add** is the same derivation re-run over the current module set
|
|
140
|
+
— idempotent (re-deriving an unchanged set is a no-op), so adding a module later
|
|
141
|
+
and re-deriving updates `architecture.yaml` to match. `deriveArchitecture` is
|
|
142
|
+
exported for that re-derivation. `marketing` is validated end-to-end; the `docs`
|
|
143
|
+
and `multi-tenant` slices are registry-defined ahead of their template trees.
|
|
23
144
|
|
|
24
145
|
## Templates are snapshotted at build time
|
|
25
146
|
|
|
@@ -30,9 +151,9 @@ populates `templates/`. The npm tarball ships the populated templates via the
|
|
|
30
151
|
|
|
31
152
|
## Repository
|
|
32
153
|
|
|
33
|
-
Source: https://github.com/
|
|
154
|
+
Source: https://github.com/working-theory-labs/ai-launch-kit
|
|
34
155
|
|
|
35
|
-
Issues: https://github.com/
|
|
156
|
+
Issues: https://github.com/working-theory-labs/ai-launch-kit/issues
|
|
36
157
|
|
|
37
158
|
## License
|
|
38
159
|
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# AILK component catalog — search by capability, not by name
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED FILE — do not hand-edit. Regenerate with `pnpm --filter create-ailk run build-catalog`. -->
|
|
4
|
+
|
|
5
|
+
The composed-component inventory of `@working-theory/ui`, the library an AI Launch Kit site is built from. It exists because a name search fails: a site rebuilt five components AILK already had, because it searched for the names IT would have used and AILK uses different ones — `ContactOverlay`→`FormLightbox`, `SearchOverlay`→`SpotlightPanel`/`NavSearchTrigger`, `SiteRail`→`SidebarNav`, `FunnelNav`→`Nav`, `NumberedWorkList`→`Steps`/`StairSteps`.
|
|
6
|
+
|
|
7
|
+
**What this file does NOT cover.** Only three tiers are indexed: `sections/`, `blocks/` and `chrome/`. The `tokens/`, `primitives/` (Button, Heading, Text, Link, Icon, Badge, Input, Dialog, Command, Tooltip, `ThemeToggle`, …) and `panels/` (FixedPanel, ResizablePanel, CardGrid, …) tiers are **absent from this file**. Finding nothing here does not mean AILK lacks it — check `packages/ui/src/primitives` and `packages/ui/src/panels` before concluding anything about a low-level control.
|
|
8
|
+
|
|
9
|
+
**Before you build a component, search this file for what it DOES.**
|
|
10
|
+
|
|
11
|
+
1. Read **Find by capability** below — it maps the words people actually type to the names AILK uses.
|
|
12
|
+
2. If nothing matches, grep the per-tier tables for a verb or noun from your requirement (`grep -i backdrop`, `grep -i "multi-step"`), not for your working name for the component.
|
|
13
|
+
3. Check the primitives and panels tiers, which this file does not index (see above).
|
|
14
|
+
4. Only then build. If you do build, you are declaring the capability is genuinely absent.
|
|
15
|
+
|
|
16
|
+
Inventory: **187 component files** across 3 tiers — 56 sections, 113 blocks, 18 chrome. 186 distinct names: `SchedulerEmbed` exists in more than one tier as genuinely different components, listed once per tier with its own source path.
|
|
17
|
+
|
|
18
|
+
Description coverage: **187/187** components carry a capability description derived from source — 40 from the section registry's hand-authored when-to-use text, 113 from the component's own doc-comment header, 34 from its tier barrel's roster line. No component was given a sentence invented from its name.
|
|
19
|
+
|
|
20
|
+
Of those, **175** are *strong* — a capability sentence you could match a requirement against — and **12** are *weak*: either one short clause, or a long one that spends itself on wiring (client boundaries, class names, which primitives it composes) instead of on what the thing is for. Weak rows are marked `(weak)` and listed in full under [Weak descriptions](#weak-descriptions). Coverage is 100%, but **findable-without-luck coverage is 94%**.
|
|
21
|
+
|
|
22
|
+
That grade is **mechanical**. It counts what it can measure — how much a description adds beyond the component's own name, how much of it is spent on wiring, whether the extraction came out damaged — and it cannot tell a fluent paragraph about the wrong subject from a useful one. A person reading these tables will find more rows unusable than the weak count admits. Treat it as a floor on the problem, not a measurement of it, and read the source before concluding a capability is absent.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Find by capability
|
|
27
|
+
|
|
28
|
+
The left column is search vocabulary — how a person phrases the need. It is hand-authored (no source file calls `FormLightbox` a "contact overlay"), but every component named on the right is checked against the live inventory when this file is generated, so a row can never point at a component that no longer exists.
|
|
29
|
+
|
|
30
|
+
| If you are looking for… | Use | Notes |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| contact overlay · modal form · popup form · form in a dialog · form on a dimmed backdrop · lightbox form | `FormLightbox` (sections) · `VideoLightbox` (blocks) · `SpotlightPanel` (sections) · `ContactForm` (sections) | FormLightbox is the modal-form one: a trigger opens a multi-step form inside a Radix Dialog on a dimmed/blurred backdrop (focus trap, ESC/backdrop close, scroll lock, lazy mount). ContactForm is the INLINE form — do not mistake it for the overlay and rebuild the overlay. |
|
|
33
|
+
| search overlay · command palette · cmd-K · ⌘K search · spotlight · quick find | `NavSearchTrigger` (blocks) · `DocsSearch` (blocks) · `AskAiCommandGroup` (blocks) · `SpotlightPanel` (sections) | Read this one carefully: AILK does NOT ship a site-wide ⌘K palette. It ships the PARTS — NavSearchTrigger (the ⌘K trigger pill), DocsSearch (trigger + CommandDialog over a Fumadocs-shaped index, docs-scoped), AskAiCommandGroup (a CommandGroup you drop into your own dialog), and the Command/CommandDialog primitives in `packages/ui/src/primitives`. Composing a site palette from these is expected; forking the dialog is not. SpotlightPanel is the dimmed-backdrop centered-card band — it hosts a form/flow, not a search index. |
|
|
34
|
+
| site rail · vertical nav column · left rail · app sidebar · icon rail · dashboard sidebar | `SidebarNav` (chrome) · `SidebarNavRailItems` (chrome) · `DocsSidebar` (chrome) · `SidePanel` (chrome) | Pick by context: SidebarNav is the DASHBOARD rail (it hardcodes a teams section and a user footer, and is the `sidebar` prop of DashboardShell) — fighting it into a marketing site is the wrong call; DocsSidebar is the DOCS rail (takes a page tree); SidebarNavRailItems is SidebarNav's collapsed icon-rail row. SidePanel is the RIGHT edge, not a left rail. |
|
|
35
|
+
| funnel nav · minimal chrome with one CTA · stripped-down header · landing-page nav · one-action header · sticky CTA | `Nav` (chrome) · `SectionNav` (chrome) · `FloatingCta` (chrome) | There is no separate funnel-nav component, and there does not need to be: this is a CONFIGURATION of Nav — pass it one action and no link list. SectionNav is the in-page section jump nav; FloatingCta is the persistent floating single-action affordance. |
|
|
36
|
+
| numbered work list · ordered steps · process list · how it works · 1-2-3 steps · staircase | `Steps` (blocks) · `StepFlow` (sections) · `StairSteps` (sections) · `FlowStepper` (sections) | For a numbered LIST you want Steps (presentational block) or StairSteps (staggered staircase section). StepFlow and FlowStepper are listed because the phrase collides, but they are the interactive multi-step FORM and its progress indicator — not a work list. |
|
|
37
|
+
| accordion · collapsible · expand/collapse · show more · disclosure | `FaqItem` (blocks) · `FAQ` (sections) · `Objection` (sections) | There is no standalone Accordion — the expand/collapse behavior lives in FaqItem and the FAQ/Objection sections that compose it. |
|
|
38
|
+
| banner · announcement bar · cookie consent · notification strip | `Banner` (chrome) · `AlertSection` (sections) | Banner is chrome (announcement + consent, with dismiss/consent islands); AlertSection is the in-page dismissible strip. |
|
|
39
|
+
| logo wall · client logos · trusted by · partner marks | `LogoCloud` (sections) · `Awards` (sections) | |
|
|
40
|
+
| pricing table · plan comparison · feature matrix · tier cards | `Pricing` (sections) · `PricingTierCard` (blocks) · `ComparisonMatrix` (blocks) · `ComparisonTable` (sections) · `BillingToggle` (blocks) | |
|
|
41
|
+
| avatar stack · people grid · about-us team · bios | `Team` (sections) · `TeamMemberCard` (blocks) | |
|
|
42
|
+
| booking · scheduling · calendar · pick a time · appointment | `Booker` (sections) · `SchedulerEmbed` (blocks) | Booker is the in-page day-strip/slot-grid transaction; SchedulerEmbed is the third-party provider iframe. |
|
|
43
|
+
| sign in · sign up · login form · oauth buttons · account menu | `AuthPanel` (sections) · `AuthCard` (blocks) · `AccountMenu` (chrome) | |
|
|
44
|
+
| email capture · newsletter signup · subscribe box | `Newsletter` (sections) · `NewsletterFormInline` (blocks) · `NewsletterDetail` (blocks) | |
|
|
45
|
+
| video player · embedded video · video modal | `VideoSection` (sections) · `VideoEmbed` (blocks) · `VideoLightbox` (blocks) | |
|
|
46
|
+
| image slider · gallery · carousel · lightbox for images | `Carousel` (sections) · `Gallery` (sections) · `MediaBand` (sections) | |
|
|
47
|
+
| locale switcher · language picker · region selector · view toggle | `LocaleSwitcher` (blocks) · `MarkdownViewToggle` (blocks) | Dark-mode switching is `ThemeToggle`, a PRIMITIVE — primitives and panels are outside this catalog's three indexed tiers. Import it from `@working-theory/ui/primitives`. |
|
|
48
|
+
| table of contents · on-page nav · jump links · sticky outline | `SectionNav` (chrome) · `DocsTocButton` (blocks) · `DocumentChassis` (sections) | |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Sections (56)
|
|
53
|
+
|
|
54
|
+
Page-level content bands. Most are MDX-driven (authored by `type` in page frontmatter and dispatched by `SectionRenderer`); a few are composed directly in a route.
|
|
55
|
+
|
|
56
|
+
Import: `import { X } from "@working-theory/ui/sections";` (or from the `@working-theory/ui` root barrel). Components marked *internal* are not re-exported — they are implementation details of a sibling in the same tier.
|
|
57
|
+
|
|
58
|
+
| Component | What it does | How to use it |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| `AlertSection` | A compact, dismissible in-page alert strip — use for a confirmation or status notice (e.g. a delivery-page 'your download is on its way' message), typically the first section on the page. Bounded to success/info/warning tone; dismissal persists per-visitor. | MDX `type: alert` |
|
|
61
|
+
| `AlertSectionDismissIsland` | Dismiss state + × button for AlertSection. Mirrors the chrome Banner's dismiss-persistence precedent (`packages/ui/src/chrome/BannerDismissIsland.tsx`): a localStorage-backed dismissed flag, read on mount and written on dismiss, with graceful degradation when localStorage is unavailable (SSR, iframe, quota, etc.). | internal — compose from `packages/ui/src/sections/AlertSectionDismissIsland.tsx` |
|
|
62
|
+
| `AskAi` | Use above the footer — hands the visitor to a third-party AI seeded with the entity question. Bounded to five measured providers (ChatGPT/Claude/Google AI/Grok/Perplexity), each deep-linked with an authored prompt. The `ticker` variant renders a compact full-width band instead of the default headline/description/provider-row layout. | MDX `type: ask-ai` |
|
|
63
|
+
| `AuthPanel` | A sign-in/sign-up panel with an optional bounded OAuth provider row (google, github) — UI-contract only, no auth backend; submit and provider clicks are callback props the composing page wires up. | MDX `type: auth-panel` · `import { AuthPanel } from "@working-theory/ui/sections"` |
|
|
64
|
+
| `Awards` | A two-column evidence band — headline/CTA left, up to 5 award or press badges right — use for third-party recognition (badges may render as labeled placeholders until real marks are supplied). | MDX `type: awards` |
|
|
65
|
+
| `BentoGrid` | A mixed-span mosaic of feature cards — use for a visually varied capability overview. | MDX `type: bento-grid` · `import { BentoGrid } from "@working-theory/ui/sections"` |
|
|
66
|
+
| `BlogList` | A blog post list with pagination — use for the blog index page only. | MDX `type: blog-list` · `import { BlogList } from "@working-theory/ui/sections"` |
|
|
67
|
+
| `BlogPost` | A single blog post body with TOC and related posts — use only on the blog-post chassis. | MDX `type: blog-post` · `import { BlogPost } from "@working-theory/ui/sections"` |
|
|
68
|
+
| `Booker` | The custom booker — use on a scheduling page where the whole see-days/pick-slot/confirm transaction should land in the page itself rather than a provider iframe (the `scheduler-embed` alternative). Authors supply only `calLink` plus optional eyebrow/headline framing; duration, meeting type, and timezone are DERIVED from the calendar via /v1/schedule/availability and can never be typed into content. | MDX `type: booker` |
|
|
69
|
+
| `BookerIsland` | The island owns exactly two things: the state machine, and the two calls across the scheduling seam. It talks to `/v1/schedule/availability` and `/v1/schedule/book` — never to a provider — so the day this deploy flips to the self-hosted engine, nothing in this file changes. | internal — compose from `packages/ui/src/sections/BookerIsland.tsx` |
|
|
70
|
+
| `Carousel` | An image carousel/slider — use for a sequential set of visual items in constrained space. | MDX `type: carousel` · `import { Carousel } from "@working-theory/ui/sections"` |
|
|
71
|
+
| `ComparisonTable` | A general-purpose entity-vs-entity comparison — use for /vs pages, not tied to pricing plans. | MDX `type: comparison-table` |
|
|
72
|
+
| `ContactChannels` | A support channel directory — use to list alternate ways to reach the team (icon + title + description + CTA). | MDX `type: contact-channels` · `import { ContactChannels } from "@working-theory/ui/sections"` |
|
|
73
|
+
| `ContactForm` | A contact form with typed fields — use as the primary conversion action on Contact pages. | MDX `type: contact-form` · `import { ContactForm } from "@working-theory/ui/sections"` |
|
|
74
|
+
| `ContentBlock` | Long-form prose with optional media — use for narrative explanation that doesn't fit a card grid. | MDX `type: content-block` |
|
|
75
|
+
| `CTA` | A focused call-to-action block — use to end a page or section with one clear next step. | MDX `type: cta` · `import { CTA } from "@working-theory/ui/sections"` |
|
|
76
|
+
| `DecisionSplit` | An honest either-option decision block — use on /vs pages before any comparison. | MDX `type: decision-split` |
|
|
77
|
+
| `Definition` | A single-term definition callout — use for one prominent 'What is X?' answer-first block. | MDX `type: definition` |
|
|
78
|
+
| `DocumentChassis` | A long-read document page (privacy policy, terms, DPA, working agreement) — chrome-free header + optional stat strip + a sticky numbered section nav beside continuous prose; one document per page/route. The authored `sections` list drives both the nav and the body. | MDX `type: document-chassis` |
|
|
79
|
+
| `FAQ` | Question-and-answer pairs — use to pre-empt buyer objections that are naturally phrased as questions. | MDX `type: faq` · `import { FAQ } from "@working-theory/ui/sections"` |
|
|
80
|
+
| `Feature` | A multi-item benefit/feature highlight grid — use to walk through several product capabilities. | MDX `type: feature` |
|
|
81
|
+
| `FlowStepper` | Rendering a served flow config as a real multi-step form. | `import { FlowStepper } from "@working-theory/ui/sections"` |
|
|
82
|
+
| `FormLightbox` | The VideoLightbox dialog shell hosting a StepFlow instead of a video: a trigger (e.g. a "Let's Start" Button — any focusable element the caller supplies) opens the SAME StepFlow inside a Radix Dialog on the dimmed/blurred backdrop shared with VideoLightbox/SpotlightPanel. | `import { FormLightbox } from "@working-theory/ui/sections"` |
|
|
83
|
+
| `Gallery` | An image gallery — use to showcase product screenshots or visual work. | MDX `type: gallery` · `import { Gallery } from "@working-theory/ui/sections"` |
|
|
84
|
+
| `GlossaryIndex` | An A-Z glossary index — use for a browsable list of defined terms. | MDX `type: glossary-index` · `import { GlossaryIndex } from "@working-theory/ui/sections"` |
|
|
85
|
+
| `Hero` | Top-of-page introduction — headline, optional subhead and CTAs; use once per page as the first section. | MDX `type: hero` · `import { Hero } from "@working-theory/ui/sections"` |
|
|
86
|
+
| `HeroFormSlot` | The panel hero's right-column gate card: a `FormCard` wrapping either the consumer's conversational intake (when eligible and a `HeroIntakeProvider` is mounted) or the embedded multi-step `StepFlow`, which is also where `controls.showForm` hands the surface over. /. | `import { HeroFormSlot } from "@working-theory/ui/sections"` |
|
|
87
|
+
| `HeroIntakeContext` | The bounded seam through which a consumer page mounts its own conversational intake as the FIRST surface INSIDE one of Hero's existing gate surfaces (the `lightboxCta` FormLightbox, or the panel variant's form-slot card), with the existing multi-step StepFlow as the in-gate fallback (correcting 's whole-page swap). | `import { HeroIntakeContext } from "@working-theory/ui/sections"` |
|
|
88
|
+
| `HeroPromptCapture` | The Hero `promptCapture` opt-in's wiring. Composes the two new blocks — `PromptCaptureCard` (the chat-style card) and `SuggestionChipCarousel` (the one-expanded-slot chip row) — and owns the ONE piece of state they share: the typed text. A chip click writes into it; the card renders and edits it; submit carries it onward. | `import { HeroPromptCapture } from "@working-theory/ui/sections"` |
|
|
89
|
+
| `HeroQuickSearch` | Surfaces the existing ⌘K quick-search as an inline trigger inside the hero CTA cluster (Chassis 2). It does NOT re-roll a search input: it composes the SearchInputTrigger primitive (an input-style control at CTA height) plus the Command palette primitive, so there is ONE search mechanism. The nav's compact 24px ⌘K pill stays as-is — the hero reads as a search INPUT, matching the 44px "Get Started" CTA. | internal — compose from `packages/ui/src/sections/HeroQuickSearch.tsx` |
|
|
90
|
+
| `Items` | A general-purpose card/items grid — use for services, use cases, or any homogeneous list of cards. | MDX `type: items` · `import { Items } from "@working-theory/ui/sections"` |
|
|
91
|
+
| `ListingApplicationFlow` | This is the thing a consuming site mounts INSTEAD of hand-writing three proxy routes, a save-on-advance form, and a decision about where a bearer token lives. | `import { ListingApplicationFlow } from "@working-theory/ui/sections"` |
|
|
92
|
+
| `LogoCloud` | A customer/partner logo wall — use for trust-by-association social proof. | MDX `type: logoCloud` · `import { LogoCloud } from "@working-theory/ui/sections"` |
|
|
93
|
+
| `MDXContent` | The keystone the docs route and blog both render their compiled MDX through. | `import { MDXContent } from "@working-theory/ui/sections"` |
|
|
94
|
+
| `MediaBand` | A single full-width image band — use for the 1-up visual moment Gallery's 2-column minimum can't express (e.g. between pricing plan columns); renders a labeled placeholder until a real image is supplied. | MDX `type: media-band` · `import { MediaBand } from "@working-theory/ui/sections"` |
|
|
95
|
+
| `ModuleAbsent` | What a slice section renders when its module is not here. The oss dispatch table must name a component for every `SectionName`, and `booker`'s real component strips with the scheduling slice. This is the entry it names instead; a slice that IS installed registers over it through `registerSliceRenderer`. | internal — compose from `packages/ui/src/sections/ModuleAbsent.tsx` |
|
|
96
|
+
| `Newsletter` | An email signup form — use for a low-commitment conversion ask. | MDX `type: newsletter` · `import { Newsletter } from "@working-theory/ui/sections"` |
|
|
97
|
+
| `Objection` | Objection-and-response pairs — use for you-might-think rhetoric that isn't phrased as a question. | MDX `type: objection` |
|
|
98
|
+
| `PaymentReceipt` | A checkout payment outcome — use only on a checkout Delivery/confirmation page to show status + receipt details. | MDX `type: payment-receipt` · `import { PaymentReceipt } from "@working-theory/ui/sections"` |
|
|
99
|
+
| `Pricing` | A plan comparison — the page's pricing decision surface; six variants cover tables, toggles, single-price offers, and add-on grids. | MDX `type: pricing` · `import { Pricing } from "@working-theory/ui/sections"` |
|
|
100
|
+
| `PricingTable` | A grid of subscription plan tiers that SUBSCRIBE — the capability-bearing twin of the `Pricing` CMS section (which renders href-based marketing tier CTAs, no live Stripe call). `PricingTable` is scaffolded by `scaffold-commerce` (not registered in `SectionRenderer`'s CMS dispatch table) and each tier's action POSTs to the subscription surface's `subscribeHandler` route + redirects to the returned Stripe Checkout URL — the same `onCheckout`-callback shape `CheckoutForm` uses for one-time products. | `import { PricingTable } from "@working-theory/ui/sections"` |
|
|
101
|
+
| `ProjectListingShelves` | Two shelves of ProjectListingCards partitioned from ONE list of public listing rows: `status === "active"` on one shelf, `status === "closed"` on the other. `closed` is COMPUTED by the API read (the window-end check lives server-side, / D6b) — this component never recomputes it, it only reads the field. | `import { ProjectListingShelves } from "@working-theory/ui/sections"` |
|
|
102
|
+
| `SchedulerEmbed` | A declarative third-party booking iframe (e.g. Google Calendar Appointment Schedules) — use for a booking/scheduling moment; sets the provider's cookies on load, so a site classifying it as non-essential may wrap it in a consent gate. | MDX `type: scheduler-embed` · `import { SchedulerEmbed } from "@working-theory/ui/sections"` · `packages/ui/src/sections/SchedulerEmbed.tsx` |
|
|
103
|
+
| `SectionEmpty` | The shared empty-state body every section's `*Empty` variant delegates to. | `import { SectionEmpty } from "@working-theory/ui/sections"` |
|
|
104
|
+
| `SectionRenderer` | Typed dispatch table. Maps a section's `type` discriminant to its React component. | `import { SectionRenderer } from "@working-theory/ui/sections"` |
|
|
105
|
+
| `Separator` | An inter-section spacer — use to add rhythm or a visible rule between two sections that need more separation than default spacing gives. | MDX `type: separator` · `import { Separator } from "@working-theory/ui/sections"` |
|
|
106
|
+
| `SocialProof` | Tweet/post-shaped social proof items — use for lightweight, screenshot-style endorsements. | MDX `type: social-proof` · `import { SocialProof } from "@working-theory/ui/sections"` |
|
|
107
|
+
| `SplitContentMedia` | Lays out a SectionHeader (text, one side) beside a media slot (the other side) — the HubSpot/wealthsmyth split content+media pattern. | `import { SplitContentMedia } from "@working-theory/ui/sections"` |
|
|
108
|
+
| `SpotlightPanel` | A full-width dimmed/blurred backdrop (abstract pattern or product image) behind a centered elevated card carrying a headline, support text, and a form/flow embed — use for a demo or signup moment that needs focus without leaving the page flow (apollo.io /demo pattern). | MDX `type: spotlight-panel` · `import { SpotlightPanel } from "@working-theory/ui/sections"` |
|
|
109
|
+
| `StairSteps` | A 2-5 step staircase — use for process/journey narratives where direction carries meaning (an ascending 'up-right' staircase for a build-up story, a descending 'down-right' one for the conversionfactory.co 'from idea to impact' pattern). | MDX `type: stair-steps` · `import { StairSteps } from "@working-theory/ui/sections"` |
|
|
110
|
+
| `Stats` | A number-led credibility row — use to show scale or outcome metrics. An optional leadQuote can front the row with an analyst quote (staggered variant mirrors apollo.io's mixed-size evidence band). | MDX `type: stats` |
|
|
111
|
+
| `StepFlow` | A data-driven multi-step lead-capture form (one small field group per step, progress affordance, per-step advance) — use for a longer qualifying gate where a single-step ContactForm would feel too long; fires onStepComplete after each step so an abandoned flow still captures a partial lead. | MDX `type: step-flow` · `import { StepFlow } from "@working-theory/ui/sections"` |
|
|
112
|
+
| `Tabs` | Tabbed content panels — use to let a reader choose between parallel content without scrolling. | MDX `type: tabs` · `import { Tabs } from "@working-theory/ui/sections"` |
|
|
113
|
+
| `Team` | A team member grid — use on About pages to introduce the people behind the product. | MDX `type: team` · `import { Team } from "@working-theory/ui/sections"` |
|
|
114
|
+
| `Testimonials` | Direct customer quotes — use for first-person social proof with attribution. | MDX `type: testimonials` |
|
|
115
|
+
| `VideoSection` | The standard large-centered-video section (acquisition.com/workshop pattern) — optional headline/intro above a bounded-width centered video, optional caption/CTA below; renders a labeled placeholder until a real source is supplied. | MDX `type: video-section` · `import { VideoSection } from "@working-theory/ui/sections"` |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Blocks (113)
|
|
120
|
+
|
|
121
|
+
Intermediate composition tiles — the pieces sections are built from. Compose primitives and panels; never import a section.
|
|
122
|
+
|
|
123
|
+
Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-theory/ui` root barrel). Components marked *internal* are not re-exported — they are implementation details of a sibling in the same tier.
|
|
124
|
+
|
|
125
|
+
| Component | What it does | How to use it |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| `AddonCard` | Apollo.io-pattern add-on tile: header-area eyebrow+name+price, optional qualifier/CTA, titled or plain-string feature rows with a selectable checkmark tone (Pricing addons variant). | `import { AddonCard } from "@working-theory/ui/blocks"` |
|
|
128
|
+
| `AddressFieldset` | The composite control for StepFlow's "address" field type. No such component existed in the library before this — built by composing the existing Field/Input/Select primitives, no bespoke markup, no new primitive. Mirrors PhoneNumberField's division of labor for the "tel" field type: this block renders the six named controls; the consuming section combines/reads them, it does no combining itself. | `import { AddressFieldset } from "@working-theory/ui/blocks"` |
|
|
129
|
+
| `AgentContextCard` | Capability-bearing block that renders agent provenance. RSC note: no hooks or browser APIs — server-renderable by default. *(weak)* | `import { AgentContextCard } from "@working-theory/ui/blocks"` |
|
|
130
|
+
| `ArticleHeaderAtoms` | They define the title / meta-line / tags / back-link / action-bar treatment ONCE so the docs and blog headers cannot drift. `DocsArticleHeader` (top layout) and `BlogPostHeader` (sticky-rail layout) are thin wrappers that COMPOSE these atoms — there is no `layout` switch or stack of `show*` booleans; the two arrangements differ only in which atoms each wrapper places and in what order. | `import { ArticleHeaderAtoms } from "@working-theory/ui/blocks"` |
|
|
131
|
+
| `ArticlePager` | The footer prev/next pager. Given the previous and next destinations — docs pages in tree order, or blog posts in date order — renders two link tiles (a directional label + the destination title). Either side may be absent (first / last item) — the present side still anchors to its edge. Renders nothing when both sides are absent. | `import { ArticlePager } from "@working-theory/ui/blocks"` |
|
|
132
|
+
| `AskAiCommandGroup` | The ⌘K palette's composable "Ask AI" group; one CommandItem per provider seeding "About <entity>: <query>" (or the entity promptText when the query is empty); composed by the consumer's own CommandDialog. | `import { AskAiCommandGroup } from "@working-theory/ui/blocks"` |
|
|
133
|
+
| `AskAiProviderRow` | The ONE shared provider-link row every ask-AI placement composes — the AskAi section (band + ticker variant) and the Hero `askAi` opt-in all render THIS block, never a per-placement fork. Renders a bounded set of five measured providers, each a deep link seeded with an AUTHORED `promptText` — the prompt is always consumer-supplied data, never derived from page context (headline, entity name, etc.). | `import { AskAiProviderRow } from "@working-theory/ui/blocks"` |
|
|
134
|
+
| `AuthCard` | Logo (top-center, inside). Axes: intent: "sign-in" \| "sign-up" — drives heading / subhead / footer copy. method: "password" \| "magic-link" \| "sso" — drives the body + primary action. | `import { AuthCard } from "@working-theory/ui/blocks"` |
|
|
135
|
+
| `AwardBadgePlaceholder` | The labeled placeholder an Awards badge slot renders when no image has been supplied — mirrors MediaPlaceholder's role but in an award-chevron/ laurel badge silhouette rather than a generic photo frame, since an unfilled award slot should read as "an award badge goes here," not "a photo goes here." The shape (a laurel-flanked medallion over a chevron ribbon) is a hand-drawn SVG outline — never a copied G2/Capterra/Apollo asset. | internal — compose from `packages/ui/src/blocks/AwardBadgePlaceholder.tsx` |
|
|
136
|
+
| `BackgroundPattern` | Decorative SVG dot-grid / line pattern for ContactForm section. Decorative block (generalized beyond its original single consumer). Renders an absolutely-positioned decoration behind a section's content. Originally the pattern anchored behind ContactForm's form column; SpotlightPanel composes it as a full-bleed section backdrop (dimmed + blurred, behind a centered card) — same block, a second placement. | `import { BackgroundPattern } from "@working-theory/ui/blocks"` |
|
|
137
|
+
| `BadgeRow` | Horizontal cluster of static badge labels used by Hero and Feature section families for `data.badge` and tag-list patterns. | `import { BadgeRow } from "@working-theory/ui/blocks"` |
|
|
138
|
+
| `BillingToggle` | Monthly / Annual billing period toggle for the Pricing section. Purely presentational — click handlers come from the parent (Pricing section). No "use client" needed at the block level; the parent Pricing section is "use client" and passes the callbacks down. | `import { BillingToggle } from "@working-theory/ui/blocks"` |
|
|
139
|
+
| `BlogPostHeader` | Layout: the better-auth sticky left rail — eyebrow ← back-link · decorative title · author byline · date/reading-time meta · tags. Per the title here is DECORATIVE (aria-hidden): the semantic `<h1>` is rendered atop the right content column by `BlogPost` (bodyOnly), so the page keeps exactly one heading. | `import { BlogPostHeader } from "@working-theory/ui/blocks"` |
|
|
140
|
+
| `BookerAttendeeFields` | TWO FIELDS. A booking needs somewhere to send the invite and a name to put on it; every additional field is one more reason to abandon a transaction the user had already decided to complete. Notes, phone, and company are deliberately absent — the provider collects them after the invite lands, if the operator wants them at all. | internal — compose from `packages/ui/src/blocks/BookerAttendeeFields.tsx` |
|
|
141
|
+
| `BookerDateStrip` | ONLY DAYS THAT HAVE OPEN SLOTS APPEAR. That is the structural argument this block makes, and the reason the composition is a horizontal strip rather than the month grid every booking widget reaches for: a month grid spends its whole area rendering the ~24 days you cannot book, then needs a second interaction to reveal which of the remaining six are live. | internal — compose from `packages/ui/src/blocks/BookerDateStrip.tsx` |
|
|
142
|
+
| `BookerEventHeader` | TWO KINDS OF TEXT, AND THE DIFFERENCE MATTERS. `eyebrow` and `headline` are AUTHORED: the operator's words about why someone would book. Everything in the meta row — duration, meeting type, timezone — is DERIVED from the calendar on the availability read, which is why the section schema has no field for any of it. | internal — compose from `packages/ui/src/blocks/BookerEventHeader.tsx` |
|
|
143
|
+
| `BookerPanel` | The booking card, fully controlled. One chassis, five views, ONE FOOTER. | internal — compose from `packages/ui/src/blocks/BookerPanel.tsx` |
|
|
144
|
+
| `BookerSlotGrid` | The selected day's open times. Two columns at 48px on mobile — the measured pixel target — widening to three at `lg` so the desktop variant shows more of the day without scrolling. Two columns is not an arbitrary density: at 390px it is the widest grid where a time still reads at a glance, and it puts eight times (a full working day's openings) inside one thumb-reachable block. | internal — compose from `packages/ui/src/blocks/BookerSlotGrid.tsx` |
|
|
145
|
+
| `BrandLogo` | Brand identity lockup (mark + wordmark + badge slot) as a home link. Brand identity lockup for Nav, Footer, and other surfaces. | `import { BrandLogo } from "@working-theory/ui/blocks"` |
|
|
146
|
+
| `Card` | The base surface-chrome block the section tier composes instead of hand-rolling `rounded + hairline border + surface + p-card` (7× duplicated at time). A block owns its visual identity: it looks the same everywhere it is composed, and a higher tier SELECTS a look via `variant` — it never patches via className. | `import { Card } from "@working-theory/ui/blocks"` |
|
|
147
|
+
| `CheckoutForm` | Product/amount selection + checkout submit for the one-time checkout surface. | `import { CheckoutForm } from "@working-theory/ui/blocks"` |
|
|
148
|
+
| `CheckoutPriceCard` | The order-summary card the flow's side panel becomes at checkout: eyebrow, offer name + description, seat/credit line items, an optional caller-supplied add-credits row, and (on the quoted arm only) total + due-today; with a `configurator` it also renders the in-card seat stepper, period toggle, add-on credits row and on-demand breakdown, pricing itself with the pure `price`. | `import { CheckoutPriceCard } from "@working-theory/ui/blocks"` |
|
|
149
|
+
| `ChoiceCard` | Onboarding "Is this you?" disambiguation card — reimplements the ploy.ai persona-disambiguation capture: a researched candidate option vs a "none of these are me" option, confirmed by the user ("a human-input seam the user answers to orient the agent"). Purely presentational and props-driven: renders options + an optional "none of these" option + a confirm action, disabled until a selection is made. | `import { ChoiceCard } from "@working-theory/ui/blocks"` |
|
|
150
|
+
| `CodeBlock` | Read-only code display with syntax highlighting. Modeled on the Claude docs code-block pattern. | `import { CodeBlock } from "@working-theory/ui/blocks"` |
|
|
151
|
+
| `ComparisonMatrix` | Full feature × tier comparison matrix for the Pricing 'with-comparison-table' variant. Renders N collapsible ComparisonGroups, each containing M feature rows with per-tier values. | `import { ComparisonMatrix } from "@working-theory/ui/blocks"` |
|
|
152
|
+
| `Composer` | The chat input, per the ploy.ai capture contract. | `import { Composer } from "@working-theory/ui/blocks"` |
|
|
153
|
+
| `ContactChannelItem` | Renders one support channel entry: colored icon square + headline + description paragraph + CTA link (with trailing arrow icon). | `import { ContactChannelItem } from "@working-theory/ui/blocks"` |
|
|
154
|
+
| `ContactFormFields` | Renders the form field grid (Input / Textarea / Select primitives) + submit Button + optional consent text footer. | `import { ContactFormFields } from "@working-theory/ui/blocks"` |
|
|
155
|
+
| `ContactInfoAside` | For ContactForm 'split-with-pattern' variant. Renders address / phone / email contact info rows. Each row: sr-only <dt> label + visible <dd> with Icon + Text. Phone and email render as tel:/mailto: links (click-to-call / click-to-email). | `import { ContactInfoAside } from "@working-theory/ui/blocks"` |
|
|
156
|
+
| `ConversationalIntake` | The UI half of the conversational-intake feature: renders the transcript, closed-question answer pills, a free-text form, a thinking indicator, and Skip — driven entirely through the `NextTurn` interface exported by `./engine` (merged). | internal — compose from `packages/ui/src/blocks/conversational-intake/ConversationalIntake.tsx` |
|
|
157
|
+
| `DescriptionList` | Semantic <dl> of aligned term/definition rows (rows + inline layouts). A semantic <dl> rendering label/value rows from an `items` prop. Each item is a <dt> (muted, min-width-aligned term) paired with a <dd> (value). The value is a ReactNode, so callers compose richer values (spans, lists, mono text) inside it. | `import { DescriptionList } from "@working-theory/ui/blocks"` |
|
|
158
|
+
| `DetailCard` | The collapsible console / data-panel card: a composable card with a header (title + optional actions + collapse toggle), an optional tab bar, a body slot, and an optional footer. The "deferred SidePanel DetailCard" from, built as a general content card any console / detail view can compose without inventing its own card structure. | `import { DetailCard } from "@working-theory/ui/blocks"` |
|
|
159
|
+
| `DetailHeader` | The entity-bearing sibling of PageHeader: a Breadcrumb wayfinding trail above an EntityHeader identity row, plus a forwarded actions slot. | `import { DetailHeader } from "@working-theory/ui/blocks"` |
|
|
160
|
+
| `DistributionList` | Per-option answer-share list over the Progress primitive. One question's answer distribution: a title, an "answered" count line, and one row per declared option (a label, a pre-formatted share `display` string, and a `Progress` bar). `display` is pre-formatted by the caller (Rule 10 — this block never formats numbers itself); `share` drives the `Progress` fill, scaled to the primitive's 0–100 range. | `import { DistributionList } from "@working-theory/ui/blocks"` |
|
|
161
|
+
| `DocsActionBar` | The agent-facing article toolbar that lands in the DocsArticleHeader `actionBar` slot, presented as the Claude-docs **"Copy page ▾" split button**. The in-page rendered↔markdown toggle is NOT reimplemented here — that is the existing MarkdownViewToggle block, which the route mounts around the article body. This bar only adds the copy + open-in affordances. | `import { DocsActionBar } from "@working-theory/ui/blocks"` |
|
|
162
|
+
| `DocsArticleHeader` | The article header: a breadcrumb trail (with the TOC popover button at its inline-end), the page title (the single <h1>), an optional lead description, and an "updated" meta line. Leaves an `actionBar` slot for the Phase-5 DocsActionBar (markdown toggle / copy / share) — empty until then. | `import { DocsArticleHeader } from "@working-theory/ui/blocks"` |
|
|
163
|
+
| `DocsFeedback` | The article-footer feedback widget: a "Was this helpful?" thumbs yes/no pair plus an "Edit this page on GitHub" link. Clicking a thumb records the answer (fires a `gtag` analytics event when the site's GA is present) and, on "no", reveals an optional free-text note. After answering, the prompt is replaced with a thank-you line. | `import { DocsFeedback } from "@working-theory/ui/blocks"` |
|
|
164
|
+
| `DocsSearch` | The cmd-K documentation search: a ⌘K trigger pill (NavSearchTrigger) that opens a CommandDialog over a passed-in search index. Typing filters the index by title/description (cmdk's built-in filter, fed a `value` that bundles both); selecting a result navigates there. | `import { DocsSearch } from "@working-theory/ui/blocks"` |
|
|
165
|
+
| `DocsTocButton` | Clicking the `List`-icon button opens a Popover rendering the shared `TableOfContents` (styling preserved). Esc / outside-click closes it (Radix default); in-page anchor jumps work as they do in the rail. The button renders nothing when there are no TOC entries, so the breadcrumb row stays clean on heading-less / `wide` pages. | `import { DocsTocButton } from "@working-theory/ui/blocks"` |
|
|
166
|
+
| `EntityHeader` | The single identity-row source: an optional leading avatar, a title/name (Heading), an optional subtitle/meta line (Text), an optional type-badge slot above the title, and an optional trailing actions slot. | `import { EntityHeader } from "@working-theory/ui/blocks"` |
|
|
167
|
+
| `FaqItem` | Q&A pair block for FAQ section families (expanded + accordion). Defaults reproduce the current render except the deliberate item-spacing-asymmetry fix. | `import { FaqItem } from "@working-theory/ui/blocks"` |
|
|
168
|
+
| `FeatureCard` | Icon badge + title + a short check-list + an optional "Learn more" link — the card used in HubSpot's right-hand product grid. Generalizes the inline card markup currently hand-rolled in sections/Feature.tsx. | `import { FeatureCard } from "@working-theory/ui/blocks"` |
|
|
169
|
+
| `FeatureCardGrid` | Responsive column schedule (mobile-first, uniform cells): base. Uniform responsive grid of FeatureCard tiles. Strictly equal-span cells at every breakpoint; use BentoGrid for variable-span layouts. | `import { FeatureCardGrid } from "@working-theory/ui/blocks"` |
|
|
170
|
+
| `FloatingBar` | Z-40 (spec) — the same rung Nav's sticky bar and FloatingCta already occupy; no new z-index token. The same-slot takeover works by DOM ORDER, not a higher z: a `position="sticky"` FloatingBar rendered later in the document (inside body content, after the nav) paints over a `fixed` FloatingBar at equal z-40 once it sticks, given an `opaque` surface. | internal — compose from `packages/ui/src/blocks/FloatingBar.tsx` |
|
|
171
|
+
| `FlowSidePanel` | The per-view side panel of the flow/recommender surface. ONE CHASSIS, THREE VIEWS. | `import { FlowSidePanel } from "@working-theory/ui/blocks"` |
|
|
172
|
+
| `FooterBottomBar` | Separator + copyright line (+ optional trailing social). Bottom bar with a single top divider + copyright line. | `import { FooterBottomBar } from "@working-theory/ui/blocks"` |
|
|
173
|
+
| `FooterNav` | Data-driven footer nav: flat row or titled columns (row/columns layout). These two renderings of the same footer-link data were used mutually-exclusively by the chrome `Footer`'s `layout` switch — collapsing them removes a real either/or the parent managed. | `import { FooterNav } from "@working-theory/ui/blocks"` |
|
|
174
|
+
| `FormCard` | Stateless, centered max-w-md form-card chassis: a Card wrapping an optional title + description header, a field-stack body (children), and a footer slot for the primary action + a secondary line below it. The SHARED look composed by both the contact-form section's 'card' variant and the auth-panel section — this block owns none of their field/state machinery, only the surrounding chrome. | `import { FormCard } from "@working-theory/ui/blocks"` |
|
|
175
|
+
| `InviteMemberDialog` | The invite modal — reimplements the ploy.ai "Invite Team Member" capture (Email textbox + Role select, default Member, options Member/Admin, helper "Admins can invite and remove members." + Send Invitation). | `import { InviteMemberDialog } from "@working-theory/ui/blocks"` |
|
|
176
|
+
| `InvoiceForm` | Draft-invoice creation form. Creates a draft invoice (single line item), for the invoice surface (U4). | `import { InvoiceForm } from "@working-theory/ui/blocks"` |
|
|
177
|
+
| `InvoiceList` | Capability-bearing invoice rows (status + amount + hosted-invoice link). A customer's invoice rows, shared by the invoice surface (U4). Capability-bearing: binds a schema.org `Invoice` resource-payload fragment per row (imported from `@working-theory/schema`) — so a co-located `.text.ts` + `.text.test.ts` renderer is required and gated by `scripts/check-ax-parity.sh`. | `import { InvoiceList } from "@working-theory/ui/blocks"` |
|
|
178
|
+
| `KeyPointsPanel` | ONE shared block composed by two consumers: Hero's `panel` variant (text-left / panel-right) and Pricing's `band-hero` arrangement (header-left / panel-right, tiers below). | internal — compose from `packages/ui/src/blocks/KeyPointsPanel.tsx` |
|
|
179
|
+
| `LinkCard` | A whole-tile link card: the entire tile IS the anchor (Claude-docs link-card anatomy). Optional leading icon, a title heading, and an optional description paragraph. Hover fill + chrome are intrinsic to the block — never props. | `import { LinkCard } from "@working-theory/ui/blocks"` |
|
|
180
|
+
| `LinkListItem` | Hub-page spoke list row: prose Link + optional description, enlarged to the 44px touch-target floor. Fix: the enlarged-hit-area pattern (same idiom as ShortcutTrigger, SegmentedControl's touchTargetFloor) — `min-h-(control-height-big)` clamps the anchor's clickable box to 44px while `inline-flex items-center` keeps the visible text at its normal prose size. | `import { LinkListItem } from "@working-theory/ui/blocks"` |
|
|
181
|
+
| `ListingFullPreview` | The full-page-preview `custom` step renderer. The founder's assembled application, rendered as a page, with an edit link back to the step that owns each rendered part. Purely presentational: every entry's label and formatted value arrive pre-built on `entries` (this block does no formatting of its own), and `onEdit` is the only way it ever changes anything — it never mutates, saves, or fetches. | `import { ListingFullPreview } from "@working-theory/ui/blocks"` |
|
|
182
|
+
| `ListingPrivacyNotice` | The per-listing privacy notice. It names the FOUNDER — not the platform — as the party collecting a visitor's personal data, and it renders ON THE FLOW (where a visitor submits answers), not on the listing page. | `import { ListingPrivacyNotice } from "@working-theory/ui/blocks"` |
|
|
183
|
+
| `ListingQuestionReview` | The edit-only question-review `custom` step renderer. The founder is refining a diagnostic template the SITE authored, not composing one from nothing (`projectListingQuestionsSchema`, `packages/validation/src/schemas/project-listings.ts`). | `import { ListingQuestionReview } from "@working-theory/ui/blocks"` |
|
|
184
|
+
| `ListingTilePreview` | The founder's tile, as it will look, updating as they type. | `import { ListingTilePreview } from "@working-theory/ui/blocks"` |
|
|
185
|
+
| `LocaleSwitcher` | Compact globe + locale dropdown. Extracts the "🌐 English ▾" affordance that lived as an inline node in the chrome Footer story into a reusable block. Composes the `Select` primitive (NOT a raw <select>): a leading globe icon, the current locale label (via SelectValue), and the trigger's built-in chevron. | `import { LocaleSwitcher } from "@working-theory/ui/blocks"` |
|
|
186
|
+
| `LogoRow` | The ONE logo-strip implementation; bounded layout/treatment/logoSize plus an opt-in motion-safe marquee; composed by the LogoCloud section and the Hero logoStrip opt-in. | `import { LogoRow } from "@working-theory/ui/blocks"` |
|
|
187
|
+
| `MarkdownViewToggle` | 2-state rendered ↔ markdown view toggle for content pages. The human complement to the agent-facing /llms.txt surface. Mirrors the Claude-docs "view/copy as markdown" affordance. Ships at Tier 3 (Block) because it is an interactive view-toggle control composing the SegmentedControl primitive with the CodeBlock block — not a page-level layout shell. | `import { MarkdownViewToggle } from "@working-theory/ui/blocks"` |
|
|
188
|
+
| `MediaFigure` | The reusable *frame* for the visual half of a split section: an `Image` constrained by an optional `AspectRatio`, with consistent rounding, an optional caption, an optional decorative frame, and an optional overlay slot + scrim for text/badges/play-buttons over media. | `import { MediaFigure } from "@working-theory/ui/blocks"` |
|
|
189
|
+
| `MediaPlaceholder` | The single shared labeled placeholder a declared IMAGERY SLOT renders when no asset has been supplied yet — a chassis never silently ships an empty slot, and never renders an accidental image. Composed by `Hero`/`Feature`/`Gallery` (sections tier) whenever their `imagerySlot` data flag is `true` and the corresponding asset is absent. | internal — compose from `packages/ui/src/blocks/MediaPlaceholder.tsx` |
|
|
190
|
+
| `MemberList` | Settings "People" member rows — reimplements the ploy.ai Team Members list capture (avatar + email + "(you)" + role Badge). Purely presentational and props-driven: no session/permission logic; the caller supplies the member list, role labels, and an optional per-row actions slot (e.g. a "Remove" menu). | `import { MemberList } from "@working-theory/ui/blocks"` |
|
|
191
|
+
| `MetricComparisonTable` | A numeric comparison table over the Table primitive. The operator-dashboard comparison view's core surface: one column per waitlist (plus a "total" column) and one row per metric (raw, qualified, qualification rate, one row per tier). | `import { MetricComparisonTable } from "@working-theory/ui/blocks"` |
|
|
192
|
+
| `NavActionList` | CTA action cluster block (one shared button chrome; variant = paint, size = box). Extracts the action-cluster variant routing that was duplicated verbatim between Nav (ActionCluster, Nav.tsx:240–342) and NavMobileMenu (action map, NavMobileMenu.tsx:344–435). This block is the vehicle for the later Nav + NavMobileMenu refactors — both will compose it. | `import { NavActionList } from "@working-theory/ui/blocks"` |
|
|
193
|
+
| `NavFlyoutPanel` | Mega-menu body block (feature grid + action bar) for Nav flyouts. Renders the content of a flyout (mega-menu) panel opened by a NavigationMenu trigger in the Nav chrome component. | `import { NavFlyoutPanel } from "@working-theory/ui/blocks"` |
|
|
194
|
+
| `NavSearchTrigger` | ⌘K search trigger control for Nav desktop pill + mobile icon-only surfaces. ⌘K search trigger button for Nav, desktop + mobile. Thin domain wrapper over the ShortcutTrigger primitive: it resolves the i18n "Open search" label and passes the search specifics (Search icon, the ⌘/K shortcut, the onSearchOpen handler) to ShortcutTrigger. | `import { NavSearchTrigger } from "@working-theory/ui/blocks"` |
|
|
195
|
+
| `NewsletterDetail` | One "why subscribe" detail item: colored icon square + headline + description. Vertically arranged (icon top, heading + description below). Used in the right-column 2-up grid of the 'side-by-side-with-details' variant. | `import { NewsletterDetail } from "@working-theory/ui/blocks"` |
|
|
196
|
+
| `NewsletterFormInline` | Inline email signup form: email Input + submit Button side-by-side at sm+, stacked on mobile (input full-width on its own row, Subscribe below). Manages its own submit state so the parent Newsletter section can remain RSC-oriented (only this block needs the client boundary). | `import { NewsletterFormInline } from "@working-theory/ui/blocks"` |
|
|
197
|
+
| `OnboardingChecklist` | Global onboarding launcher: floating "N/5" bubble expanding into a Popover (lg+) / bottom Sheet (<lg) checklist with SegmentedProgress + item rows (ploy-capture recomposition). The global onboarding launcher captured off ploy.ai's app frame (behavior spec: `post-ftu-checklist` — "global onboarding launcher (floating, all pages)"). | `import { OnboardingChecklist } from "@working-theory/ui/blocks"` |
|
|
198
|
+
| `PageHeader` | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (DashboardShell and similar). No accent bar. No tab API. No named action props — the caller assembles whatever button/menu nodes it needs and passes them as `actions`. *(weak)* | `import { PageHeader } from "@working-theory/ui/blocks"` |
|
|
199
|
+
| `PageHeaderSwitcher` | Header-owned context-switcher island (DropdownMenu-backed). Header-owned segment switcher rendered inside PageHeader's `switcher` slot. Composes DropdownMenu (Radix-backed — positioning, click-outside, Escape, focus management, and roving keyboard nav all come for free). | `import { PageHeaderSwitcher } from "@working-theory/ui/blocks"` |
|
|
200
|
+
| `PairingCard` | Quiet card naming a matched WaitlistRecommendation pairing: both resolved offer names + the resolved reason, joined against a caller-supplied offers[] by key. | `import { PairingCard } from "@working-theory/ui/blocks"` |
|
|
201
|
+
| `PaymentLinkCard` | A single shareable Stripe Payment Link (pay-by-link surface). Renders the link's offer name, active-status chip, optional amount, and the hosted URL with a one-click copy action. | `import { PaymentLinkCard } from "@working-theory/ui/blocks"` |
|
|
202
|
+
| `PaymentLinkForm` | Product selection + "create link" submit for the pay-by-link surface. | `import { PaymentLinkForm } from "@working-theory/ui/blocks"` |
|
|
203
|
+
| `PaymentLinkList` | Presentational list composing PaymentLinkCard rows. A site owner's shareable payment links (pay-by-link surface). Composes one `PaymentLinkCard` per link. | `import { PaymentLinkList } from "@working-theory/ui/blocks"` |
|
|
204
|
+
| `PaymentResult` | Success/cancel result state for the one-time checkout surface — the terminal render a consumer's success/cancel return-URL page shows after the Stripe-hosted Checkout redirect. | `import { PaymentResult } from "@working-theory/ui/blocks"` |
|
|
205
|
+
| `PaymentStatusBadge` | Capability-bearing payment/invoice/subscription status chip. Payment-state chip shared by the invoice-status (U4) and subscription-status (U5) surfaces. | `import { PaymentStatusBadge } from "@working-theory/ui/blocks"` |
|
|
206
|
+
| `PhoneNumberField` | Single-box combo phone input for the "tel" field kind (supersedes the two-segment country-Select + number-Input layout). | `import { PhoneNumberField } from "@working-theory/ui/blocks"` |
|
|
207
|
+
| `PortalEntry` | Presentational "Manage billing" entry action, reuses U1 StripeActionButton; target of U5 SubscriptionStatus's Manage action. A standalone "Manage billing" entry point into Stripe's hosted Customer Portal — the smallest surface (spec: AILK owns only the entry; Stripe hosts the portal itself). | `import { PortalEntry } from "@working-theory/ui/blocks"` |
|
|
208
|
+
| `PostRow` | A single horizontal row in the two-column blog index: a landscape cover thumbnail (left) followed by the post's title · excerpt · author+date meta · tag list. The WHOLE row is one link (aria-labelled by the title, so screen readers announce the post title rather than the concatenated row content). | `import { PostRow } from "@working-theory/ui/blocks"` |
|
|
209
|
+
| `PricingExtraTierRow` | Compact horizontal extra-tier row for the Pricing 'two-tiers-with-extra-tier' variant. Renders plan name + description on the left and a CTA on the right. Structurally different from PricingTierCard (no price display in this variant). | `import { PricingExtraTierRow } from "@working-theory/ui/blocks"` |
|
|
210
|
+
| `PricingTierCard` | Single pricing tier card (all 4 Pricing variants). Renders a single pricing tier: plan name + optional badge, description, price display, CTA button, and feature checklist. | `import { PricingTierCard } from "@working-theory/ui/blocks"` |
|
|
211
|
+
| `PricingTierCardFeaturesDisclosure` | Phone-breakpoint (<md, 768px — the same phone/tablet step CardGrid's own mobile-stacking ramp uses) presentation of a tier card's feature list: collapsed behind a disclosure button so price + CTA (which render ABOVE this row, see PricingTierCard's row-slot ordering) fit the first card view on a phone — the wisprflow.ai/pricing pattern. `md` and up renders the SAME feature list, always expanded, in a second, non-interactive tree — desktop/tablet is unaffected by the collapse. | `import { PricingTierCardFeaturesDisclosure } from "@working-theory/ui/blocks"` |
|
|
212
|
+
| `PricingTierCardSeatControl` | Seat-count range picker for the Team tier card. Renders a Select primitive that lets the user choose an "Up to N seats" option from a caller-supplied list of numbers. The parent PricingTierCard stays a pure RSC; only this tiny island is hydrated. Pattern mirrors PageHeaderSwitcher.tsx: small "use client" island imported by an otherwise-server-rendered parent, keeping the client bundle minimal. *(weak)* | `import { PricingTierCardSeatControl } from "@working-theory/ui/blocks"` |
|
|
213
|
+
| `ProjectListingCard` | The tile for one listing on a shelf (`ProjectListingShelves`). The whole tile is a single anchor (LinkCard's bespoke-by-semantics precedent: Card renders a <div> and cannot satisfy a whole-tile-link contract, so this composes Link directly rather than Card). | `import { ProjectListingCard } from "@working-theory/ui/blocks"` |
|
|
214
|
+
| `PromptCaptureCard` | The chat-style prompt card: a multiline field carrying the authored placeholder, with a circular arrow submit control pinned bottom-right that stays muted (disabled) until the visitor has typed something. Enter submits; Shift+Enter inserts a newline — the chat-composer convention. | `import { PromptCaptureCard } from "@working-theory/ui/blocks"` |
|
|
215
|
+
| `Prose` | The single typography wrapper both the docs route and blog render their compiled-MDX body inside. It styles every RAW markdown element a compiled document emits — h2–h6, p, ul/ol/li, blockquote, table parts, hr, a, inline code, pre, img, kbd, strong/em — via `@working-theory/theme` semantic tokens and type roles. No raw color or spacing literals; dark mode rides the semantic tokens (no `dark:` variants needed). | `import { Prose } from "@working-theory/ui/blocks"` |
|
|
216
|
+
| `RecommendationCard` | "For you" proactive-recommendation tile: status + title + description + "Why this?" disclosure + context chip + action + dismiss (ploy-capture recomposition). The "For you" proactive-recommendation card captured off ploy.ai's Overview page (behavior spec: -2, — `overview-page` "For you" feed / rebuild-triage row "For you" recommendation card"). | `import { RecommendationCard } from "@working-theory/ui/blocks"` |
|
|
217
|
+
| `ResponseChart` | The single-question aggregate chart of the diagnostic's results reveal. Renders exactly ONE `FlowAggregateQuestion`. The chart type is FIXED by `question.answerType` — a closed `single \| multi` union — and there is no `chartType`/`variant` prop: an author cannot request a doughnut for a multi-select question, because there is no prop through which to ask. | `import { ResponseChart } from "@working-theory/ui/blocks"` |
|
|
218
|
+
| `ResultsReveal` | The results-reveal active-region composition: one ResponseChart per resultsReveal-flagged, aggregate-matched segmentation step, in served order. | `import { ResultsReveal } from "@working-theory/ui/blocks"` |
|
|
219
|
+
| `SchedulerEmbed` | A declarative third-party booking iframe. Renders a full-width, border-0, lazy-loaded <iframe> at `src` with a graceful loading skeleton (shown until the iframe's own `load` event fires) and a timeout-gated plain-link fallback beneath it — for environments that block third-party frames (ad blockers, a strict CSP `frame-src`) where the iframe may load blank or never load at all. | `import { SchedulerEmbed } from "@working-theory/ui/blocks"` · `packages/ui/src/blocks/SchedulerEmbed.tsx` |
|
|
220
|
+
| `SectionHeader` | Alignment-parameterized section header (eyebrow/subtitle/description/supportLink). The same component serves two ranks (headingLevel="section" \| "subsection") and three alignments (align="start" \| "center" \| "end"). It knows nothing about columns/splits/carousels — it is width-flexible and fills whatever container the section places it in. | `import { SectionHeader } from "@working-theory/ui/blocks"` |
|
|
221
|
+
| `ShareBar` | The reader-facing counterpart to DocsActionBar. Both surfaces share the same SplitButton *affordance + slot* (outline variant, right-justified on the post title row) but fill it with different actions: DocsActionBar carries the AI-ingestion set (Copy page + Open in …), ShareBar carries the social-share set (X · LinkedIn · Bluesky · Copy link). One primitive, two configs. | `import { ShareBar } from "@working-theory/ui/blocks"` |
|
|
222
|
+
| `SinglePriceCard` | 2-column split card for the Pricing 'single-price-with-details' variant. *(weak)* | `import { SinglePriceCard } from "@working-theory/ui/blocks"` |
|
|
223
|
+
| `SocialIcons` | Horizontal row of social icon links. Renders brand icons (via Icon primitive + simple-icons paths) inside accessible Link primitives. Each platform link gets an aria-label. Shared by company-mission, simple-centered, and newsletter-below footer variants, and composed by TeamMemberCard for member social links. *(weak)* | `import { SocialIcons } from "@working-theory/ui/blocks"` |
|
|
224
|
+
| `StatTicker` | Static, horizontally overflow-scrollable workspace stat strip with an optional trailing CTA; no auto-scroll marquee (ploy-capture recomposition). The Overview stat strip captured off ploy.ai (behavior spec: -2, — `overview-ticker` "-viewport"/"-track"/"-segment"/"-value"/"-cta"). | `import { StatTicker } from "@working-theory/ui/blocks"` |
|
|
225
|
+
| `Steps` | The numbered install/guide walkthrough: an ordered list of `Step` items, each a zero-padded number marker + an optional per-step heading + body, joined top-to-bottom by a connecting vertical rule. The classic docs "follow these steps" surface, rendered from `@working-theory/ui` so docs pages stay design-system citizens. | `import { Steps } from "@working-theory/ui/blocks"` |
|
|
226
|
+
| `StreamingMessage` | One chat turn's message rendering, per the ploy.ai capture contract. | `import { StreamingMessage } from "@working-theory/ui/blocks"` |
|
|
227
|
+
| `StripeActionButton` | Checkout/portal entry-point trigger with pending + test-mode affordances. The checkout/portal entry-point action button shared by the checkout (U2) and billing-portal (U6) surfaces. | `import { StripeActionButton } from "@working-theory/ui/blocks"` |
|
|
228
|
+
| `SubscriptionStatus` | Current plan + lifecycle state for the subscriptions surface — shows state via U1's `PaymentStatusBadge` plus a portal "Manage" action. | `import { SubscriptionStatus } from "@working-theory/ui/blocks"` |
|
|
229
|
+
| `SuggestionChipCarousel` | A 3-6 icon-chip row with exactly one chip expanded (muted category + bold prompt), auto-rotating motion-safe with hover/focus pause; a click hands the chip's prompt to the host. A row of 3-6 icon chips in which exactly ONE is expanded at a time. | `import { SuggestionChipCarousel } from "@working-theory/ui/blocks"` |
|
|
230
|
+
| `TableOfContents` | The shared "On this page" rail consumed by the docs shell and the blog post layout (do not couple it to docs-only context). Renders a flat list of heading anchors and scroll-spies the heading currently in view, highlighting the matching item. | `import { TableOfContents } from "@working-theory/ui/blocks"` |
|
|
231
|
+
| `TeamMemberCard` | Renders one team member in either of two layout modes: 'inline' — small circular avatar left + name/role right (with-small-images variant) 'stacked' — large circular avatar top + name/role/social-links below (with-large-images variant). | `import { TeamMemberCard } from "@working-theory/ui/blocks"` |
|
|
232
|
+
| `TestimonialAside` | For ContactForm 'with-testimonial' variant. Rating (optional 0–5): rendered via Rating primitive with accessible label. avatar (optional): composed via Avatar + AvatarFallback + AvatarImage (initials fallback). | `import { TestimonialAside } from "@working-theory/ui/blocks"` |
|
|
233
|
+
| `UserBlock` | Position-agnostic identity/account trigger block: avatar + primary label + optional secondary line, with density/affordance/collapsed/truncation variants. A single focusable button-rooted element that forwardRef's + spreads props so DropdownMenuTrigger asChild (AccountMenu) can clone it as its trigger anchor. | `import { UserBlock } from "@working-theory/ui/blocks"` |
|
|
234
|
+
| `VerifyCodeField` | Presentational code-entry unit for StepFlow's `verify` step type: a status line ("We sent a code to…"), a 6-digit numeric code Field, and a resend link. Composes existing Field/Input/Button/Text primitives — no bespoke markup, no new primitive. | `import { VerifyCodeField } from "@working-theory/ui/blocks"` |
|
|
235
|
+
| `VersionHistory` | Day-grouped auto-saved version list with a "Current" marker — reimplements the ploy.ai artifact-editor Versions capture ("10 auto-saved versions", grouped by day, `Current` on one entry). Purely presentational and props-driven: renders the grouped list only. Designed to be embedded inside a popover by a higher tier — this block does NOT render the popover/trigger itself. | `import { VersionHistory } from "@working-theory/ui/blocks"` |
|
|
236
|
+
| `VersionSwitcher` | Version-dropdown block for brand lockup accessory slots. Renders the current version label as a Badge-styled trigger pill that opens a DropdownMenu of older available versions. Designed for use in the `brandAccessory`/`badge` slot of Nav and BrandLogo so both surfaces render the version accessory identically from a single shared source. | `import { VersionSwitcher } from "@working-theory/ui/blocks"` |
|
|
237
|
+
| `VideoEmbed` | The shared video player: poster + large Play affordance (click, default) or muted autoplay with native controls, reduced-motion-aware. 'click' (default) — the acquisition.com thank-you pattern: a poster image with a large, labeled Play affordance. Nothing plays, nothing is fetched, until the visitor activates it — the video element itself only mounts on activation. | `import { VideoEmbed } from "@working-theory/ui/blocks"` |
|
|
238
|
+
| `VideoLightbox` | The shared video player, presented as a DIALOG. A trigger (a poster thumbnail, a "Watch the video" button — any focusable element the caller supplies) opens the SAME VideoEmbed inside a Radix Dialog on a dimmed/blurred backdrop. | `import { VideoLightbox } from "@working-theory/ui/blocks"` |
|
|
239
|
+
| `VideoPlaceholder` | The true-to-size, play-marked placeholder a declared VIDEO slot renders when no source has been supplied yet — the video-flavored sibling of `MediaPlaceholder`: a circle-with-centered-triangle play mark (mirroring `VideoEmbed`'s own poster/Play affordance styling) inside a dashed aspect box sized to the SAME `ratio` the real player would use, so swapping in a real source never shifts the slot's footprint. | `import { VideoPlaceholder } from "@working-theory/ui/blocks"` |
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Chrome (18)
|
|
244
|
+
|
|
245
|
+
Persistent framing UI that wraps page content — navigation, footers, sidebars, banners. Not MDX-driven.
|
|
246
|
+
|
|
247
|
+
Import: `import { X } from "@working-theory/ui/chrome";` (or from the `@working-theory/ui` root barrel). Components marked *internal* are not re-exported — they are implementation details of a sibling in the same tier.
|
|
248
|
+
|
|
249
|
+
| Component | What it does | How to use it |
|
|
250
|
+
| --- | --- | --- |
|
|
251
|
+
| `AccountMenu` | Auth-agnostic account dropdown (theme + settings + admin + sign-out). Composes the DropdownMenu primitive (Radix-backed — positioning, click-outside, Escape, focus management, and roving keyboard nav all come for free) with the Icon, Link, and ThemeToggle primitives. AccountMenu carries NO session, routing, or sign-out logic of its own: every behaviour arrives via props, so the same component serves any auth stack. | `import { AccountMenu } from "@working-theory/ui/chrome"` |
|
|
252
|
+
| `ArtifactToolbar` | Chrome-tier artifact-canvas toolbar (ploy-capture recomposition). Reimplements the captured ploy.ai artifact-canvas toolbar: artifact tab strip ("All outputs" gallery tab + per-artifact tabs with close ×) · Preview/Code toggle · Select (element-pick) toggle · history back/forward · a read-only path bar · responsive-viewport cycle · refresh · Versions dropdown trigger · Publish. | `import { ArtifactToolbar } from "@working-theory/ui/chrome"` |
|
|
253
|
+
| `Banner` | Site-wide announcement and consent banner chrome. *(weak)* | `import { Banner } from "@working-theory/ui/chrome"` |
|
|
254
|
+
| `BannerConsentIsland` | Accept / Reject action cluster for the consent Banner. Isolated to "use client" so Banner stays RSC. The onAccept / onReject callbacks must be Server Actions when used inside an RSC tree; they may be regular functions in client contexts (Storybook, testing). *(weak)* | internal — compose from `packages/ui/src/chrome/BannerConsentIsland.tsx` |
|
|
255
|
+
| `BannerDismissIsland` | Isolated to "use client" so Banner (Server Component) stays RSC. Mirrors the Nav / NavMobileMenu split: interactivity is contained here. Rendering: wraps its children in a relative-positioned div and absolutely places the × dismiss button at the end (RTL-safe: `end-4`) of the bar. *(weak)* | internal — compose from `packages/ui/src/chrome/BannerDismissIsland.tsx` |
|
|
256
|
+
| `DocsSidebar` | The left documentation rail. Consumes a `tree` prop (structurally a Fumadocs `source.pageTree` Root) and renders its folders (static section groups), pages (links), and separators (section captions / dividers). The current page is highlighted via `aria-current="page"`. Kept repo-agnostic: the route passes `docsSource.pageTree`; no nav data is hardcoded here, so a fork reuses it unchanged. | `import { DocsSidebar } from "@working-theory/ui/chrome"` |
|
|
257
|
+
| `FacetNav` | Chrome-tier faceted secondary navigation (ploy-capture recomposition). One reusable component servicing THREE captured consumers: Settings' grouped Org/Workspace nav, Assets' All + tag-facet counts, and Docs' All + folder tree + tag facets. | `import { FacetNav } from "@working-theory/ui/chrome"` |
|
|
258
|
+
| `FloatingCta` | Persistent fixed corner action pill. *(weak)* | `import { FloatingCta } from "@working-theory/ui/chrome"` |
|
|
259
|
+
| `Footer` | Site footer server component with secondary nav links. Label resolution order for navItems labels. Resolved labels are passed into FooterNav as pre-resolved strings — no duplicated resolution logic across variants. | `import { Footer } from "@working-theory/ui/chrome"` |
|
|
260
|
+
| `Nav` | Primary navigation server component with locale-aware links. Three layout variants supported via `navAlignment`. Flyout (mega-menu) items: the desktop link list is ALWAYS a single SectionNav render path — there is no Path A/B fork. | `import { Nav } from "@working-theory/ui/chrome"` |
|
|
261
|
+
| `NavMobileMenu` | Client subcomponent for mobile hamburger state. Isolates "use client" to this narrow component so Nav (Server Component) stays clean. Renders a hamburger button + collapsible link list. Closes the menu automatically when the pathname changes (route navigation). *(weak)* | internal — compose from `packages/ui/src/chrome/NavMobileMenu.tsx` |
|
|
262
|
+
| `NavOverflowMenu` | The Nav row's per-breakpoint link-overflow disclosure. The desktop link row never wraps: a fixed per-breakpoint inline-link budget (4 at md, 6 at lg+) is enforced by the caller (Nav), which splits `navItems` into an inline slice and an overflow slice. This component renders ONLY the overflow slice, behind a disclosure trigger, in source order — it never computes the budget itself. | internal — compose from `packages/ui/src/chrome/NavOverflowMenu.tsx` |
|
|
263
|
+
| `NotificationsMenu` | Bell trigger + notifications popover chrome (ploy-capture app-frame). Presentational, props-driven. The unread count and row list arrive entirely via props — this component carries NO fetch/polling logic of its own. Rows are pre-formatted at the call site (relative time, heading, empty copy) per the AILK i18n/formatting convention (design-system-rules Rule 10). | `import { NotificationsMenu } from "@working-theory/ui/chrome"` |
|
|
264
|
+
| `SectionNav` | Chrome-tier route-aware section navigation. A horizontal, tab-styled section nav promoting Working Theory's bespoke `UnifiedTabs`/`TheoriesTabs` to a tokenized, tier-correct AILK component. | `import { SectionNav } from "@working-theory/ui/chrome"` |
|
|
265
|
+
| `SidebarNav` | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of DashboardShell. Wrap in a FixedPanel (panels tier) to get the expanded ↔ rail ↔ hidden state machinery. Independently reusable in future shells (settings, analytics, etc.). *(weak)* | `import { SidebarNav } from "@working-theory/ui/chrome"` |
|
|
266
|
+
| `SidebarNavRailItems` | Client boundary for the collapsed rail tooltip affordance. Isolated "use client" boundary so SidebarNav itself stays a Server Component. Renders icon-only nav links with Tooltip labels when the rail is collapsed. *(weak)* | internal — compose from `packages/ui/src/chrome/SidebarNavRailItems.tsx` |
|
|
267
|
+
| `SidePanel` | Chrome-tier right-edge content panel. Fills the ResizablePanel right-edge slot in AppShell. Provides a rich header (title / subtitle / type-badge / avatar / actions / close), a scrollable body, and an optional footer. Mirrors how SidebarNav fills the left edge. | `import { SidePanel } from "@working-theory/ui/chrome"` |
|
|
268
|
+
| `WorkspaceSwitcher` | Org/workspace switcher chrome (ploy-capture app-frame). Presentational, props-driven. Tenancy data (org, user, workspace list, credit meters, actions) arrives entirely via the optional `tenancy` prop — this component carries NO fetch/session logic of its own. When `tenancy` is absent it degrades cleanly to a static, non-interactive single-tenant identity row: no popover, no chevron, no menu semantics. | `import { WorkspaceSwitcher } from "@working-theory/ui/chrome"` |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Weak descriptions
|
|
273
|
+
|
|
274
|
+
These 12 components have a description that is accurate but does not do the job well: too short to match against, or long but spent on implementation. A capability search reaches them only if the searcher's word happens to be in it, so they are the most likely place for this catalog to repeat the failure it was built to fix. Read the source before concluding the capability is absent — and if you own one of these components, its header is the fix.
|
|
275
|
+
|
|
276
|
+
| Component | Tier | What the source gives us |
|
|
277
|
+
| --- | --- | --- |
|
|
278
|
+
| `AgentContextCard` | blocks | Capability-bearing block that renders agent provenance. RSC note: no hooks or browser APIs — server-renderable by default. |
|
|
279
|
+
| `PageHeader` | blocks | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (DashboardShell and similar). No accent bar. No tab API. No named action props — the caller assembles whatever button/menu nodes it needs and passes them as `actions`. |
|
|
280
|
+
| `PricingTierCardSeatControl` | blocks | Seat-count range picker for the Team tier card. Renders a Select primitive that lets the user choose an "Up to N seats" option from a caller-supplied list of numbers. The parent PricingTierCard stays a pure RSC; only this tiny island is hydrated. Pattern mirrors PageHeaderSwitcher.tsx: small "use client" island imported by an otherwise-server-rendered parent, keeping the client bundle minimal. |
|
|
281
|
+
| `SinglePriceCard` | blocks | 2-column split card for the Pricing 'single-price-with-details' variant. |
|
|
282
|
+
| `SocialIcons` | blocks | Horizontal row of social icon links. Renders brand icons (via Icon primitive + simple-icons paths) inside accessible Link primitives. Each platform link gets an aria-label. Shared by company-mission, simple-centered, and newsletter-below footer variants, and composed by TeamMemberCard for member social links. |
|
|
283
|
+
| `Banner` | chrome | Site-wide announcement and consent banner chrome. |
|
|
284
|
+
| `BannerConsentIsland` | chrome | Accept / Reject action cluster for the consent Banner. Isolated to "use client" so Banner stays RSC. The onAccept / onReject callbacks must be Server Actions when used inside an RSC tree; they may be regular functions in client contexts (Storybook, testing). |
|
|
285
|
+
| `BannerDismissIsland` | chrome | Isolated to "use client" so Banner (Server Component) stays RSC. Mirrors the Nav / NavMobileMenu split: interactivity is contained here. Rendering: wraps its children in a relative-positioned div and absolutely places the × dismiss button at the end (RTL-safe: `end-4`) of the bar. |
|
|
286
|
+
| `FloatingCta` | chrome | Persistent fixed corner action pill. |
|
|
287
|
+
| `NavMobileMenu` | chrome | Client subcomponent for mobile hamburger state. Isolates "use client" to this narrow component so Nav (Server Component) stays clean. Renders a hamburger button + collapsible link list. Closes the menu automatically when the pathname changes (route navigation). |
|
|
288
|
+
| `SidebarNav` | chrome | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of DashboardShell. Wrap in a FixedPanel (panels tier) to get the expanded ↔ rail ↔ hidden state machinery. Independently reusable in future shells (settings, analytics, etc.). |
|
|
289
|
+
| `SidebarNavRailItems` | chrome | Client boundary for the collapsed rail tooltip affordance. Isolated "use client" boundary so SidebarNav itself stays a Server Component. Renders icon-only nav links with Tooltip labels when the rail is collapsed. |
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Undescribed components
|
|
294
|
+
|
|
295
|
+
None — every component in the inventory carries a real description.
|