create-ailk 0.1.0 → 0.2.0
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 +456 -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 +12 -5
- 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 +78 -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 +241 -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 +558 -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 +869 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +221 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +468 -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-answers.test.ts +707 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +375 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +467 -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 +120 -0
- package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
- package/templates/apps/api/src/routes/project-listings/me.ts +76 -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 +106 -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 +307 -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__/consent-migration.test.ts +65 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +282 -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__/listing-promotion.test.ts +684 -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/consent.ts +236 -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 +1296 -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/listing-promotion.ts +342 -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 +510 -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 +1472 -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 +127 -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 +90 -27
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +112 -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 +121 -0
- package/templates/apps/web/lib/site-theme.ts +74 -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 +17 -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 +36 -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 +443 -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 +574 -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/migrations/20260911140000_listing_structured_address/migration.sql +32 -0
- package/templates/database/migrations/20260911180000_consent_grants/migration.sql +71 -0
- package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +30 -0
- package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +49 -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/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
|
@@ -38,3 +38,41 @@ STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
|
38
38
|
# Must match OSS_API_INTERNAL_SECRET in apps-paid/marketing-api/.env.local.
|
|
39
39
|
# Generate with: openssl rand -hex 32
|
|
40
40
|
# OSS_API_INTERNAL_SECRET=your-shared-secret-here
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# Scheduling — the `booker` section's provider (#4416)
|
|
44
|
+
# =============================================================================
|
|
45
|
+
# SERVER-SIDE ONLY. The browser never receives these: the booker section calls
|
|
46
|
+
# this app's /v1/schedule/availability + /v1/schedule/book, and those handlers
|
|
47
|
+
# hold the credential. Never expose any of these as NEXT_PUBLIC_*.
|
|
48
|
+
#
|
|
49
|
+
# Unset CAL_API_KEY is a supported state, not a broken one — the routes answer
|
|
50
|
+
# 503 not_configured with the provider's public booking page, and the section
|
|
51
|
+
# renders a link out to it rather than an error.
|
|
52
|
+
# CAL_API_KEY=cal_live_xxx
|
|
53
|
+
# Self-hosted Cal instances only; defaults to https://api.cal.com.
|
|
54
|
+
# CAL_API_BASE_URL=https://api.cal.com
|
|
55
|
+
# Host used to build the degraded state's link out; defaults to https://cal.com.
|
|
56
|
+
# SCHEDULING_PUBLIC_BASE_URL=https://cal.com
|
|
57
|
+
# Provider selector. Only "cal" is implemented today; the self-hosted engine
|
|
58
|
+
# (#4288) lands as a second value here with no change to the section.
|
|
59
|
+
# SCHEDULING_PROVIDER=cal
|
|
60
|
+
|
|
61
|
+
# ── Project listings — site addressing (#5048 D2) ───────────────────────────
|
|
62
|
+
# AILK_SITE_ID is this deployment's own site identifier. Unset means "default".
|
|
63
|
+
# It is read SERVER-SIDE only; no request body carries a site identifier.
|
|
64
|
+
# AILK_SITE_ID=default
|
|
65
|
+
#
|
|
66
|
+
# AILK_LISTING_PUBLIC_KEY is the PUBLIC site key an anonymous founder
|
|
67
|
+
# application and the public listings read name this site by. It is not a
|
|
68
|
+
# credential: it ships in browser JavaScript and in an agent's request, and
|
|
69
|
+
# holding it grants only what a public application form grants. The server maps
|
|
70
|
+
# it to AILK_SITE_ID.
|
|
71
|
+
#
|
|
72
|
+
# This is the SINGLE-TENANT path — the default create-ailk scaffold, one
|
|
73
|
+
# customer per deployment, no database row required. A multi-tenant deployment
|
|
74
|
+
# instead writes SiteListingConfig.public_key per site, which is consulted
|
|
75
|
+
# first. With neither set, every application and every public read answers 400
|
|
76
|
+
# unknown_site_key, which is the correct closed default but gives no clue at
|
|
77
|
+
# boot — so set this if the deployment accepts listings.
|
|
78
|
+
# AILK_LISTING_PUBLIC_KEY=
|
|
@@ -17,11 +17,24 @@ Every endpoint here has a 1:1 MCP tool in `apps/mcp`. When you add, change, or r
|
|
|
17
17
|
Routes are versioned under `/v1/*`:
|
|
18
18
|
|
|
19
19
|
- `/v1/leads/{submit,subscribe,callback}` — lead capture, newsletter subscription, callback request
|
|
20
|
+
- `/v1/flows/:slug` (GET), `/v1/flows/:slug/steps` (POST) — serve a flow config + submit a step's answers; server-side per-step partial-state persistence (#3956)
|
|
21
|
+
- `/v1/flows/:slug/aggregate` (GET) — anonymous, site-scoped per-question response counts across all completed respondents for the results reveal (#4771): respondents are completed `FlowSession` rows (not `Lead` rows — a recommending-mode respondent has no Lead until the email moment), question metadata + the chart flag come from the `WaitlistExperiment` register, and only `resultsReveal`-flagged `single`/`multi` questions are returned (`src/services/flow-aggregate.ts`). No individual answer, email, name, session id, or score in the response; no auth. No MCP twin — recorded exception (an agent walking a flow already gets everything it needs from `submit_flow_step`'s own response; "how everyone else answered" changes none of it).
|
|
22
|
+
- `/v1/flows/:slug/save` (POST), `/v1/flows/:slug/checkout` (POST) — the recommender's email moment (#4841): `save` creates the FlowSession + Lead (+ the T+0 DeliverableGrant) for the permalink's answers; `checkout` does the same, records the `FlowCheckout` buyer row at a SERVER-recomputed `price()` (the body carries no amount — `flowCheckoutInputSchema` is strict), and opens a Stripe TEST-mode Checkout Session whose metadata carries the permalink + offer key (`src/routes/flows/recommender.ts`, `src/services/recommender-capture.ts`, `packages/stripe-client`'s `createQuotedCheckoutSession`). Anonymous, rate-limited; a non-`sk_test_` key is refused before any side effect. No MCP twin — recorded exception: an agent walking a flow has no email to give and no card to pay with; the anonymous MCP surface is identity-blind.
|
|
20
23
|
- `/v1/content/{types,:type,:type/:slug}` — public content reads
|
|
21
24
|
- `/v1/auth/tokens`, `/v1/user/{profile,data/:key}` — local auth + user data
|
|
22
25
|
- `/v1/checkout/sessions` — start a Stripe checkout
|
|
26
|
+
- `/v1/workspaces/:workspaceId/{theme,identity,seo}` (GET/PUT) — per-workspace site config (multi-tenant module)
|
|
27
|
+
- `/v1/billing` (GET), `/v1/billing/portal-session` (POST) — org-scoped billing read + Stripe customer-portal session creation
|
|
28
|
+
- `/v1/schedule/availability` (GET), `/v1/schedule/event-meta` (GET), `/v1/schedule/book` (POST) — anonymous scheduling proxy behind the provider seam (`src/services/scheduling/`); Cal.com v2 today, a self-hosted engine later, same three calls. `event-meta` is the meta-only read (title · duration · description · price) so rendering an event's facts never fetches an availability window (#4633). `CAL_API_KEY` is read server-side only. MCP twins: `list_availability` / `get_event_meta` / `create_booking` (#4416, #4633)
|
|
29
|
+
- `/v1/aeo/score` (POST), `/v1/aeo/score/example` (GET) — anonymous instant AEO score for a respondent-supplied URL, and the bundled pre-launch example, both fed by the SSRF-guarded crawler at `@working-theory/aeo/fetch` and the pure scorer at `@working-theory/aeo` (`src/services/aeo-score.ts`, #4666). No MCP twin — recorded exception, brief D7 (exposing an arbitrary-URL crawler to anonymous agents is a security-posture decision; `apps/mcp/src/tools/audit.ts` deliberately stays same-origin-locked instead).
|
|
30
|
+
- `/v1/waitlist-experiments` (GET), `/v1/waitlist-experiments/:experimentId` (GET), `/v1/waitlist-experiments/:experimentId/signups` (GET), `/v1/waitlist-experiments/:experimentId/signups/:leadId` (GET) — the operator-dashboard read API for Parallel Waitlist Validation (#4665 D7, B0): tenant-scoped list + rollup, per-waitlist comparison, paginated signups, and a signup drill-down over A1's `WaitlistExperiment` / `WaitlistScore` / `Lead` rows (`src/services/waitlist-dashboard.ts`, #4671). Role floor `owner|admin` (signup PII); the platform-operator scope (`isSentinel(organizationId) && role === "owner"`, ALSO requiring `AILK_OPERATOR_EMAIL` to be set — fail-closed, PR #4687) sees every site, an ordinary owner/admin sees only its own `siteId`. No MCP twin — identity-bound tenant routes (#3591 exception, same shape as `/v1/billing/*`).
|
|
31
|
+
- `/v1/waitlist-signups/me` (GET, `?experimentKey=<slug>`) — the respondent read (#4731): a signed-in, **email-verified** user's OWN newest signup for one experiment (`experimentKey`, `waitlistKey`, `completedAt`, `tier`, `score`, `aeoScore`, `answers.q3` — seven fields, nothing more; `src/services/waitlist-signups.ts` is the only read path). Registered in `authScope` only (auth, no tenant guard — a respondent has no workspace). Identity is `request.userId`; the email is the `User`'s, never a parameter; `emailVerified !== true` → 403 `email_unverified` before any `Lead` read; no match → 404 `signup_not_found`; every read scoped to `currentSiteId()`. No MCP twin — identity-bound (#3591 exception).
|
|
32
|
+
- `/v1/flow-checkouts/me` (GET) — the respondent purchases read (#4984, FEAT-022 M2): a signed-in, **email-verified** user's OWN `FlowCheckout` rows, newest first, `[]` when none (`id`, `flowSlug`, `experimentKey`, `offerKey`, `status`, `amountMinor`, `currency`, `period`, `completedAt`, `createdAt` — ten fields, nothing more; `src/services/flow-checkouts.ts` is the only read path). Registered in `authScope` only, beside `/v1/waitlist-signups/me`. Identity is `request.userId`; rows are joined through the promotion link (`Lead.promotedUserId = userId`, `src/services/lead-promotion.ts`) — never by an email, and no query parameter is read; `emailVerified !== true` → 403 `email_unverified` before any `Lead` read; every read scoped to `currentSiteId()`. No MCP twin — identity-bound (#3591 exception).
|
|
33
|
+
- `/v1/project-listings/me` (GET) — the FOUNDER'S OWN listings read (#5295): a signed-in user's own `ProjectListing` rows, newest first, `[]` when none. Registered in `authScope` only, beside `/v1/flow-checkouts/me` — a founder is not a workspace member, so the tenant guard's default-deny would answer 403 for their own submission. Identity is `request.userId`; rows are joined through the owner link (`ProjectListing.ownerUserId = userId`, stamped by `src/services/listing-promotion.ts`) — **never** by `founderEmail`, at any stage, and no query parameter is read. `founderEmail` is an unverified string typed into an anonymous form, so a read-time email match would hand one of two people sharing an address the other's submission. The row shape is `projectListingDraftSchema` (the founder-facing shape the anonymous draft read already uses — no `siteId`, `leadId`, `decidedBy`, `issueUrl`, or `experimentKey`). The route is ADDITIVE: `PROJECT_LISTING_ROLES` stays `owner|admin` and the tenant-scoped list/get/patch routes are unchanged. No MCP twin — identity-bound (#3591 exception).
|
|
23
34
|
|
|
24
|
-
|
|
35
|
+
The workspace site-config routes are **identity-bound tenant routes** (guarded by the tenant preHandler; the write scope is the caller's active workspace, never a body-supplied id). Like the sibling `/v1/workspaces/*` routes they have **no anonymous MCP twin** — the OSS MCP surface is identity-blind (`apps/mcp/CLAUDE.md`), so the "1:1 MCP tool" rule above does not apply to them; the tenant-scoped authed MCP surface is tracked in #3591. The `/v1/billing/*` and `/v1/waitlist-experiments/*` routes are the same shape — identity-bound tenant routes, admin/settings-facing rather than agent-facing, no MCP twin.
|
|
36
|
+
|
|
37
|
+
AEO Layer 1 scoring runs both ways: locally as a CLI command (`ailk audit`, filesystem content-root input) AND behind the anonymous `/v1/aeo/score` HTTP endpoint above (external-URL input, #4666) — the CLI's content-root audit and the route's crawler-fed score are two different input paths over the same underlying scorer, not a contradiction.
|
|
25
38
|
|
|
26
39
|
JSON in, JSON out. Validate inputs with `@working-theory/validation`. Response envelope:
|
|
27
40
|
|
|
@@ -36,12 +49,56 @@ Capture → persist (DB or file) → notify operator → return success. That's
|
|
|
36
49
|
|
|
37
50
|
Routing rules, enrichment, dedupe, webhook fan-out, CRM integration live in `@working-theory/lead-routing`, loaded via JWT entitlement check. Never hardcode routing logic here — the boundary is what makes paid additive.
|
|
38
51
|
|
|
52
|
+
## Services (billing-ledger)
|
|
53
|
+
|
|
54
|
+
- `src/services/usage-metering.ts` — the write path for a completed AI call: cost → markup → write, in one `$transaction` (`UsageEvent` insert + `UsagePeriod` upsert).
|
|
55
|
+
- `src/services/usage-aggregation.ts` — sums an org/period's `UsageEvent` rows into the `UsageBillingReport` row (meter → aggregate → report).
|
|
56
|
+
- `src/services/usage-credits.ts` — the credit waterfall; the sanctioned tenant-scope exception that reads/writes `Organization`'s on-demand credit balance.
|
|
57
|
+
|
|
58
|
+
These own every billing-ledger mutation — don't write `UsageEvent`/`UsagePeriod`/`UsageBillingReport`/`Organization` balance fields from a route handler directly.
|
|
59
|
+
|
|
39
60
|
## Persistence
|
|
40
61
|
|
|
41
62
|
- DB adapter is the default. File fallback exists for zero-config OSS use.
|
|
42
63
|
- Don't assume a DB is configured. Read `AILK_DB_URL` and degrade gracefully.
|
|
43
64
|
- Migrations in `database/migrations`. Never edit a shipped migration — add a new one.
|
|
44
65
|
|
|
66
|
+
## Scheduled sweeps (external cron)
|
|
67
|
+
|
|
68
|
+
Stateless, idempotent bins an external scheduler runs (Vercel Cron / GitHub
|
|
69
|
+
Actions cron / plain crontab) — this repo has no queue or in-process timer
|
|
70
|
+
(D1). Dev: `pnpm --filter @working-theory/api <script>`. Production:
|
|
71
|
+
`node dist/bin/<name>.js`, on whatever cadence the deployment chooses;
|
|
72
|
+
a SEQUENTIAL re-run is always a no-op for already-processed rows, via each
|
|
73
|
+
sweep's own DB constraint (never a caller-side lock).
|
|
74
|
+
|
|
75
|
+
- `abandon:sweep` (`src/bin/abandon-sweep.ts`, #3962) — sends (or audits, in
|
|
76
|
+
`dark` mode) the configured `abandonEmail` follow-up for an incomplete flow
|
|
77
|
+
session past its `delayMinutes` window. Idempotent via `FlowSession.abandonEmailStatus`.
|
|
78
|
+
- `followup:sweep` (`src/bin/followup-sweep.ts`, #4732) — sends each due
|
|
79
|
+
`(lead, followUpKey)` pair from a completed flow session's `followUps`
|
|
80
|
+
register, tier-gated and suppressed on a booked call or a Resend
|
|
81
|
+
unsubscribe. Idempotent via `waitlist_followup_sends`'
|
|
82
|
+
`@@unique([leadId, followUpKey])`; a CONCURRENT overlapping run racing the
|
|
83
|
+
same pair is caught (the unique-constraint violation is swallowed and
|
|
84
|
+
logged, not surfaced as a sweep failure) rather than aborting the whole
|
|
85
|
+
run — the narrow race window between the idempotency check and the send
|
|
86
|
+
itself is not closed (a genuinely overlapping invocation could still
|
|
87
|
+
double-send that one email), so avoid overlapping invocations of the same
|
|
88
|
+
bin; a missed tick is still harmless either way.
|
|
89
|
+
- `listing-csv:sweep` (`src/bin/listing-csv-sweep.ts`, #5001) — the WEEKLY
|
|
90
|
+
founder CSV: for each `live` `ProjectListing`, the `WaitlistScore` rows for
|
|
91
|
+
its experiment newer than the last `ListingCsvSend` become one CSV, stored
|
|
92
|
+
as a `DeliverableAsset` (`listing-{slug}-{yyyy-mm-dd}`, `text/csv`), granted
|
|
93
|
+
to the founder's own `Lead`, and emailed as a
|
|
94
|
+
`GET /v1/deliverables/:grantId` capability link — the founder's list with no
|
|
95
|
+
login. Idempotent via the `ListingCsvSend` watermark: no signup newer than
|
|
96
|
+
the last send means no asset, no grant, no email. The stamp is written only
|
|
97
|
+
after a SUCCESSFUL send, so a failed send leaves those rows for the next
|
|
98
|
+
run rather than losing them. Per-listing failures are logged (PII-safe) and
|
|
99
|
+
never stop the listings after them. The CONSUMER schedules this weekly;
|
|
100
|
+
this repo adds no cron of its own.
|
|
101
|
+
|
|
45
102
|
## Error handling
|
|
46
103
|
|
|
47
104
|
- Never leak stack traces in responses. Log them, return a code.
|
|
@@ -61,3 +118,23 @@ Routing rules, enrichment, dedupe, webhook fan-out, CRM integration live in `@wo
|
|
|
61
118
|
- Don't return 200 with `{ ok: false }`.
|
|
62
119
|
- Don't read MDX directly — use `@working-theory/content-adapters`.
|
|
63
120
|
- Don't put session state in `apps/api`. It's stateless.
|
|
121
|
+
|
|
122
|
+
Last updated: 2026-09-12 — doc-sync: added `GET /v1/project-listings/me` (#5295), the auth-scoped founder read joined on the owner link, to Endpoint conventions — verified against `apps/api/src/routes/project-listings/me.ts` and `apps/api/src/server.ts`.
|
|
123
|
+
|
|
124
|
+
Prior: 2026-09-07 — doc-sync: added `listing-csv:sweep` (#5001), the weekly founder-CSV sweep, to `## Scheduled sweeps (external cron)` — verified against `apps/api/src/bin/listing-csv-sweep.ts` and `apps/api/package.json`.
|
|
125
|
+
|
|
126
|
+
Prior: 2026-09-04 — doc-sync: added the `## Scheduled sweeps (external cron)` section documenting `abandon:sweep` and `followup:sweep` (#4732 AC-6) — verified against `apps/api/package.json` and `apps/api/src/bin/`.
|
|
127
|
+
|
|
128
|
+
Prior: 2026-09-04 — doc-sync: added `GET /v1/waitlist-signups/me` (#4731), the auth-scoped respondent read, to Endpoint conventions — verified against `apps/api/src/routes/waitlist-signups/index.ts` and `apps/api/src/server.ts`.
|
|
129
|
+
|
|
130
|
+
Prior: 2026-09-02 — doc-sync: noted the `AILK_OPERATOR_EMAIL` fail-closed precondition on the platform-operator scope in the `/v1/waitlist-experiments/*` row (PR #4687 security review, High finding) — verified against `apps/api/src/services/waitlist-dashboard.ts`.
|
|
131
|
+
|
|
132
|
+
Prior: 2026-09-02 — doc-sync: added `/v1/waitlist-experiments/*` routes (#4665 D7, #4671) to Endpoint conventions — verified against `apps/api/src/routes/waitlist-experiments/index.ts`.
|
|
133
|
+
|
|
134
|
+
Prior: 2026-08-31 — doc-sync: added `GET /v1/schedule/event-meta` (#4633), the meta-only scheduling read, to the `/v1/schedule/*` row — verified against `apps/api/src/routes/schedule/index.ts`.
|
|
135
|
+
|
|
136
|
+
Prior: 2026-08-26 — doc-sync: added `/v1/schedule/*` routes (#4416) to Endpoint conventions — verified against `apps/api/src/routes/schedule/index.ts`.
|
|
137
|
+
|
|
138
|
+
Prior: 2026-08-10 — doc-sync: added `/v1/flows/*` routes (#3956) to Endpoint conventions — verified against `apps/api/src/routes/flows/index.ts`.
|
|
139
|
+
|
|
140
|
+
Prior: 2026-07-15 — doc-sync: added `/v1/billing/*` routes (#3701) to Endpoint conventions; added the `## Services (billing-ledger)` section documenting `usage-metering.ts` / `usage-aggregation.ts` / `usage-credits.ts` — verified against `apps/api/src/routes/billing/index.ts` and `apps/api/src/services/`.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for describing the origin of the Work and
|
|
141
|
+
reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Support. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or support.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 Tailwind AI
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
@@ -1,144 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vercel Serverless Function Handler for Customer Template Backend
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Thin re-export — the adapter logic lives in ../src/vercel-handler.ts so it
|
|
5
|
+
* sits under apps/api/src, which is what both tsconfig.json's `include` and
|
|
6
|
+
* jest.config.cjs's `roots` reach (this apps/api/api/ directory is outside
|
|
7
|
+
* both, so nothing here is type-checked or tested directly).
|
|
4
8
|
*/
|
|
5
|
-
|
|
6
|
-
import { logger } from '@working-theory/observability';
|
|
7
|
-
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
|
8
|
-
|
|
9
|
-
import type { build as buildServer } from '../src/server.js';
|
|
10
|
-
|
|
11
|
-
type FastifyServer = Awaited<ReturnType<typeof buildServer>>;
|
|
12
|
-
|
|
13
|
-
// Import the build function from server
|
|
14
|
-
async function getBuildFunction(): Promise<typeof buildServer> {
|
|
15
|
-
try {
|
|
16
|
-
const srcModule = await import('../src/server.js');
|
|
17
|
-
logger.info('[Vercel Handler] Using server from src/server.js');
|
|
18
|
-
return srcModule.build;
|
|
19
|
-
} catch (srcError) {
|
|
20
|
-
logger.error(
|
|
21
|
-
{
|
|
22
|
-
err: srcError instanceof Error ? srcError.message : String(srcError),
|
|
23
|
-
stack: srcError instanceof Error ? srcError.stack : undefined,
|
|
24
|
-
},
|
|
25
|
-
'[Vercel Handler] Failed to import server',
|
|
26
|
-
);
|
|
27
|
-
throw new Error(`Cannot find server module: ${srcError instanceof Error ? srcError.message : String(srcError)}`, { cause: srcError });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Initialize build function
|
|
32
|
-
const buildPromise = getBuildFunction();
|
|
33
|
-
let serverInstance: FastifyServer | null = null;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get or create the Fastify server instance
|
|
37
|
-
*/
|
|
38
|
-
async function getServer() {
|
|
39
|
-
if (!serverInstance) {
|
|
40
|
-
logger.info('[Vercel Handler] Building server instance...');
|
|
41
|
-
const startTime = Date.now();
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const buildTimeout = new Promise<never>((_, reject) => {
|
|
45
|
-
setTimeout(() => reject(new Error('Server build timeout after 10s')), 10000);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const build = await Promise.race([buildPromise, buildTimeout]);
|
|
49
|
-
logger.info('[Vercel Handler] Build function obtained, creating server...');
|
|
50
|
-
|
|
51
|
-
const initTimeout = new Promise<never>((_, reject) => {
|
|
52
|
-
setTimeout(() => reject(new Error('Server initialization timeout after 10s')), 10000);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
serverInstance = await Promise.race([build(), initTimeout]);
|
|
56
|
-
|
|
57
|
-
const buildTime = Date.now() - startTime;
|
|
58
|
-
logger.info({ buildTime }, '[Vercel Handler] Server built successfully');
|
|
59
|
-
} catch (error) {
|
|
60
|
-
const buildTime = Date.now() - startTime;
|
|
61
|
-
logger.error({ err: error, buildTime }, '[Vercel Handler] Failed to build server');
|
|
62
|
-
throw new Error(`Server build failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return serverInstance;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Vercel serverless function handler
|
|
70
|
-
*/
|
|
71
|
-
export default async function handler(
|
|
72
|
-
req: VercelRequest,
|
|
73
|
-
res: VercelResponse
|
|
74
|
-
): Promise<void> {
|
|
75
|
-
const timeout = setTimeout(() => {
|
|
76
|
-
if (!res.headersSent) {
|
|
77
|
-
logger.error('[Vercel Handler] Request timeout');
|
|
78
|
-
res.status(504).json({
|
|
79
|
-
error: 'Gateway Timeout',
|
|
80
|
-
message: 'Request took too long to process',
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}, 25000);
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
logger.info({ method: req.method, url: req.url }, '[Vercel Handler] Starting request');
|
|
87
|
-
|
|
88
|
-
const server = await getServer();
|
|
89
|
-
|
|
90
|
-
const url = new URL(req.url || '/', 'http://localhost');
|
|
91
|
-
const pathname = url.pathname;
|
|
92
|
-
|
|
93
|
-
logger.info({ method: req.method, pathname }, '[Vercel Handler] Processing request');
|
|
94
|
-
|
|
95
|
-
const fastifyRequest = {
|
|
96
|
-
method: req.method || 'GET',
|
|
97
|
-
url: pathname,
|
|
98
|
-
headers: req.headers as Record<string, string>,
|
|
99
|
-
body: req.body,
|
|
100
|
-
query: req.query as Record<string, string>,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const response = await server.inject(fastifyRequest);
|
|
104
|
-
|
|
105
|
-
logger.info({ status: response.statusCode }, '[Vercel Handler] Response status');
|
|
106
|
-
|
|
107
|
-
clearTimeout(timeout);
|
|
108
|
-
|
|
109
|
-
res.status(response.statusCode);
|
|
110
|
-
|
|
111
|
-
Object.entries(response.headers).forEach(([key, value]) => {
|
|
112
|
-
if (value !== undefined && !res.headersSent) {
|
|
113
|
-
const headerValue = Array.isArray(value)
|
|
114
|
-
? value.map((v) => String(v)).join(', ')
|
|
115
|
-
: String(value);
|
|
116
|
-
res.setHeader(key, headerValue);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
if (!res.getHeader('Content-Type') && !res.headersSent) {
|
|
121
|
-
res.setHeader('Content-Type', 'application/json');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (!res.headersSent) {
|
|
125
|
-
const body = typeof response.body === 'string'
|
|
126
|
-
? response.body
|
|
127
|
-
: JSON.stringify(response.body);
|
|
128
|
-
|
|
129
|
-
res.send(body);
|
|
130
|
-
logger.info('[Vercel Handler] Response sent successfully');
|
|
131
|
-
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
clearTimeout(timeout);
|
|
134
|
-
|
|
135
|
-
logger.error({ err: error }, '[Vercel Handler] Error handling request');
|
|
136
|
-
|
|
137
|
-
if (!res.headersSent) {
|
|
138
|
-
res.status(500).json({
|
|
139
|
-
error: 'Internal Server Error',
|
|
140
|
-
message: error instanceof Error ? error.message : String(error),
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
9
|
+
export { default } from '../src/vercel-handler.js';
|
|
@@ -30,8 +30,21 @@ module.exports = {
|
|
|
30
30
|
// forms to the same shared mock.
|
|
31
31
|
'^@working-theory/database$': '<rootDir>/src/lib/__mocks__/prisma-client.js',
|
|
32
32
|
'^.*database/generated/client/(index|client)\\.(js|ts)$': '<rootDir>/src/lib/__mocks__/prisma-client.js',
|
|
33
|
+
// The tenancy constants subpath (#3627) — real TS source, not a mock: the
|
|
34
|
+
// `database/tenancy.ts` module has no external boundary to fake, so map
|
|
35
|
+
// straight to source, matching the workspace-package-to-src pattern below.
|
|
36
|
+
'^@working-theory/database/tenancy$': '<rootDir>/../../database/tenancy.ts',
|
|
37
|
+
// The flow-presets data subpath (#3958) — same real-TS-source rationale
|
|
38
|
+
// as tenancy above: FLOW_PRESETS is plain data with no external boundary
|
|
39
|
+
// to fake, so map straight to source rather than requiring a package build.
|
|
40
|
+
'^@working-theory/database/flows/presets$': '<rootDir>/../../database/flows/presets.ts',
|
|
41
|
+
// The shared listing-diagnostic scoring register (#5001) — same
|
|
42
|
+
// real-TS-source rationale as flows/presets above.
|
|
43
|
+
'^@working-theory/database/flows/listing-diagnostic$': '<rootDir>/../../database/flows/listing-diagnostic.ts',
|
|
33
44
|
// Map workspace packages to their TypeScript source so ts-jest compiles them
|
|
34
45
|
// directly (the published dist is ESM, which Jest's CJS preset can't load).
|
|
46
|
+
'^@working-theory/aeo/fetch$': '<rootDir>/../../packages/aeo/src/fetch/index.ts',
|
|
47
|
+
'^@working-theory/aeo$': '<rootDir>/../../packages/aeo/src/index.ts',
|
|
35
48
|
'^@working-theory/analytics/server$': '<rootDir>/../../packages/analytics/src/server/index.ts',
|
|
36
49
|
'^@vercel/analytics/server$': '<rootDir>/../../packages/analytics/__mocks__/vercel-analytics-server.ts',
|
|
37
50
|
'^@working-theory/common$': '<rootDir>/../../packages/common/src/index.ts',
|
|
@@ -39,11 +52,14 @@ module.exports = {
|
|
|
39
52
|
'^@working-theory/content-projection$': '<rootDir>/../../packages/content-projection/src/index.ts',
|
|
40
53
|
'^@working-theory/content-projection/node$': '<rootDir>/../../packages/content-projection/src/node.ts',
|
|
41
54
|
'^@working-theory/email$': '<rootDir>/../../packages/email/src/index.ts',
|
|
55
|
+
'^@working-theory/ids$': '<rootDir>/../../packages/ids/src/index.ts',
|
|
42
56
|
'^@working-theory/license$': '<rootDir>/../../packages/license/src/index.ts',
|
|
43
57
|
'^@working-theory/observability$': '<rootDir>/../../packages/observability/src/index.ts',
|
|
44
58
|
'^@working-theory/schema/faq$': '<rootDir>/../../packages/schema/src/faq.ts',
|
|
45
59
|
'^@working-theory/schema$': '<rootDir>/../../packages/schema/src/index.ts',
|
|
60
|
+
'^@working-theory/site-config/schema$': '<rootDir>/../../packages/site-config/src/schema/index.ts',
|
|
46
61
|
'^@working-theory/schema-pack-registry$': '<rootDir>/../../packages/schema-pack-registry/src/index.ts',
|
|
62
|
+
'^@working-theory/schema-validator$': '<rootDir>/../../packages/schema-validator/src/index.ts',
|
|
47
63
|
'^@working-theory/stripe-client$': '<rootDir>/../../packages/stripe-client/src/index.ts',
|
|
48
64
|
'^@working-theory/validation$': '<rootDir>/../../packages/validation/src/index.ts',
|
|
49
65
|
'^(\\.{1,2}/.*)\\.js$': '$1',
|
|
@@ -7,10 +7,20 @@
|
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"dev": "tsx watch src/cli.ts",
|
|
10
|
+
"abandon:sweep": "tsx src/bin/abandon-sweep.ts",
|
|
11
|
+
"followup:sweep": "tsx src/bin/followup-sweep.ts",
|
|
12
|
+
"listing-csv:sweep": "tsx src/bin/listing-csv-sweep.ts",
|
|
13
|
+
"retention:sweep": "tsx src/bin/session-retention-sweep.ts",
|
|
14
|
+
"deliverable:upload": "tsx src/bin/deliverable-upload.ts",
|
|
15
|
+
"deliverable:resend": "tsx src/bin/deliverable-resend.ts",
|
|
16
|
+
"seed:presets": "tsx src/bin/seed-presets.ts",
|
|
10
17
|
"build": "tsc",
|
|
11
18
|
"build:vercel": "cd ../../database && pnpm exec prisma generate && cd ../.. && pnpm --filter @working-theory/validation build && pnpm --filter @working-theory/api build && mkdir -p apps/api/public && echo '{}' > apps/api/public/.vercel",
|
|
12
19
|
"start": "node dist/cli.js",
|
|
13
|
-
"
|
|
20
|
+
"smoke:dev": "node -e \"const{spawn}=require('child_process');const http=require('http');const PORT=process.env.PORT||'3002';const SLUG=process.env.SMOKE_FLOW_SLUG||'smoke-check';const child=spawn('pnpm',['exec','tsx','watch','src/cli.ts'],{env:process.env,stdio:'ignore'});let done=false;function finish(code){if(done)return;done=true;try{child.kill();}catch(e){}process.exit(code);}function poll(attempt){if(attempt>40){console.error('smoke:dev - timeout waiting for server');finish(1);return;}const req=http.get({host:'127.0.0.1',port:PORT,path:'/v1/flows/'+SLUG},(res)=>{console.log('smoke:dev - GET /v1/flows/'+SLUG+' -> HTTP '+res.statusCode);res.resume();finish(0);});req.on('error',()=>{setTimeout(()=>poll(attempt+1),500);});}child.on('exit',(code)=>{if(!done){console.error('smoke:dev - child exited early with code '+code);finish(1);}});setTimeout(()=>poll(0),500);\"",
|
|
21
|
+
"smoke:build": "node -e \"const{spawn}=require('child_process');const http=require('http');const PORT=process.env.PORT||'3002';const SLUG=process.env.SMOKE_FLOW_SLUG||'smoke-check';const child=spawn('node',['dist/cli.js'],{env:process.env,stdio:'ignore'});let done=false;function finish(code){if(done)return;done=true;try{child.kill();}catch(e){}process.exit(code);}function poll(attempt){if(attempt>40){console.error('smoke:build - timeout waiting for server');finish(1);return;}const req=http.get({host:'127.0.0.1',port:PORT,path:'/v1/flows/'+SLUG},(res)=>{console.log('smoke:build - GET /v1/flows/'+SLUG+' -> HTTP '+res.statusCode);res.resume();finish(0);});req.on('error',()=>{setTimeout(()=>poll(attempt+1),500);});}child.on('exit',(code)=>{if(!done){console.error('smoke:build - child exited early with code '+code);finish(1);}});setTimeout(()=>poll(0),500);\"",
|
|
22
|
+
"smoke": "pnpm run smoke:dev && pnpm run smoke:build",
|
|
23
|
+
"lint": "tsx ../../scripts/lint-package.ts",
|
|
14
24
|
"test": "jest",
|
|
15
25
|
"test:watch": "jest --watch",
|
|
16
26
|
"test:coverage": "jest --coverage",
|
|
@@ -20,24 +30,29 @@
|
|
|
20
30
|
"db:studio": "cd ../../database && prisma studio"
|
|
21
31
|
},
|
|
22
32
|
"dependencies": {
|
|
33
|
+
"@fastify/cors": "^11.2.0",
|
|
34
|
+
"@fastify/rate-limit": "^10.3.0",
|
|
35
|
+
"@prisma/adapter-pg": "^7.8.0",
|
|
36
|
+
"@prisma/client": "^7.8.0",
|
|
37
|
+
"@working-theory/aeo": "workspace:*",
|
|
23
38
|
"@working-theory/analytics": "workspace:*",
|
|
24
39
|
"@working-theory/common": "workspace:*",
|
|
25
40
|
"@working-theory/content-adapters": "workspace:*",
|
|
26
41
|
"@working-theory/content-projection": "workspace:*",
|
|
27
42
|
"@working-theory/database": "workspace:*",
|
|
28
43
|
"@working-theory/email": "workspace:*",
|
|
44
|
+
"@working-theory/ids": "workspace:*",
|
|
29
45
|
"@working-theory/license": "workspace:*",
|
|
30
46
|
"@working-theory/observability": "workspace:*",
|
|
31
47
|
"@working-theory/schema": "workspace:*",
|
|
48
|
+
"@working-theory/site-config": "workspace:*",
|
|
32
49
|
"@working-theory/stripe-client": "workspace:*",
|
|
33
50
|
"@working-theory/validation": "workspace:*",
|
|
34
|
-
"@fastify/cors": "^11.2.0",
|
|
35
|
-
"@fastify/rate-limit": "^10.3.0",
|
|
36
|
-
"@prisma/adapter-pg": "^7.8.0",
|
|
37
|
-
"@prisma/client": "^7.8.0",
|
|
38
51
|
"dotenv": "^17.4.2",
|
|
39
|
-
"fastify": "^5.
|
|
52
|
+
"fastify": "^5.12.1",
|
|
53
|
+
"pdf-lib": "^1.17.1",
|
|
40
54
|
"pg": "^8.22.0",
|
|
55
|
+
"yaml": "^2.9.0",
|
|
41
56
|
"zod": "^4.2.1"
|
|
42
57
|
},
|
|
43
58
|
"devDependencies": {
|
|
@@ -46,6 +61,7 @@
|
|
|
46
61
|
"@types/pg": "^8.20.0",
|
|
47
62
|
"@vercel/node": "^5.8.22",
|
|
48
63
|
"jest": "^30.4.2",
|
|
64
|
+
"pdfjs-dist": "^6.3.289",
|
|
49
65
|
"prisma": "^7.8.0",
|
|
50
66
|
"ts-jest": "^29.4.11",
|
|
51
67
|
"tsx": "^4.22.4",
|