create-ailk 0.1.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/LICENSE +201 -0
- package/README.md +39 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +80 -0
- package/dist/copy.d.ts +8 -0
- package/dist/copy.js +109 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/lib/pro-callout.d.ts +12 -0
- package/dist/lib/pro-callout.js +20 -0
- package/dist/parse-args.d.ts +13 -0
- package/dist/parse-args.js +81 -0
- package/dist/programmatic.d.ts +49 -0
- package/dist/programmatic.js +89 -0
- package/dist/substitute.d.ts +31 -0
- package/dist/substitute.js +45 -0
- package/dist/validate.d.ts +8 -0
- package/dist/validate.js +70 -0
- package/package.json +47 -0
- package/templates/.claude/.gitkeep +0 -0
- package/templates/.claude/agents/web.md +80 -0
- package/templates/.claude/rules/architecture.md +62 -0
- package/templates/.claude/rules/preserve-existing-style.md +51 -0
- package/templates/.claude/skills/README.md +43 -0
- package/templates/.claude/skills/add-schema/SKILL.md +270 -0
- package/templates/.claude/skills/add-schema/references/conflict-handling.md +200 -0
- package/templates/.claude/skills/add-schema/references/file-finding.md +123 -0
- package/templates/.claude/skills/add-schema/references/schema-types.md +131 -0
- package/templates/.claude/skills/audit-site/SKILL.md +213 -0
- package/templates/.claude/skills/audit-site/references/common-errors.md +113 -0
- package/templates/.claude/skills/audit-site/references/findings-glossary.md +138 -0
- package/templates/.claude/skills/audit-site/references/severity-levels.md +114 -0
- package/templates/.claude/skills/provision-config/SKILL.md +243 -0
- package/templates/.claude/skills/provision-config/references/env-vars-template.md +184 -0
- package/templates/.claude/skills/provision-config/references/runbook-template.md +248 -0
- package/templates/.claude/skills/provision-config/references/vercel-json-template.md +98 -0
- package/templates/.claude/skills/scaffold-auth/SKILL.md +261 -0
- package/templates/.claude/skills/scaffold-auth/references/env-vars.md +91 -0
- package/templates/.claude/skills/scaffold-auth/references/oauth-app-setup.md +171 -0
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +310 -0
- package/templates/.claude/skills/scaffold-commerce/references/lookup-keys-template.md +71 -0
- package/templates/.claude/skills/scaffold-commerce/references/marketplace-brand-pages.md +83 -0
- package/templates/.claude/skills/scaffold-commerce/templates/marketplace-cta-route.tsx.tmpl +72 -0
- package/templates/.claude/skills/scaffold-page/SKILL.md +243 -0
- package/templates/.claude/skills/scaffold-page/references/page-types.md +169 -0
- package/templates/.claude/skills/scaffold-page/templates/content.mdx.tmpl +28 -0
- package/templates/.claude/skills/scaffold-page/templates/route.tsx.tmpl +28 -0
- package/templates/.claude/skills/suggest-site-pages/SKILL.md +242 -0
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +287 -0
- package/templates/.env.example +205 -0
- package/templates/.gitkeep +2 -0
- package/templates/CLAUDE.md +142 -0
- package/templates/CONVENTIONS.md +222 -0
- package/templates/README.md +110 -0
- package/templates/apps/api/.env.example +40 -0
- package/templates/apps/api/CLAUDE.md +63 -0
- package/templates/apps/api/api/index.ts +144 -0
- package/templates/apps/api/jest.config.cjs +74 -0
- package/templates/apps/api/package.json +54 -0
- package/templates/apps/api/src/__tests__/factories/content-fixture.ts +138 -0
- package/templates/apps/api/src/__tests__/factories/index.ts +70 -0
- package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +82 -0
- package/templates/apps/api/src/__tests__/index.test.ts +118 -0
- package/templates/apps/api/src/__tests__/server.test.ts +207 -0
- package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +126 -0
- package/templates/apps/api/src/__tests__/setup.ts +24 -0
- package/templates/apps/api/src/cli.ts +30 -0
- package/templates/apps/api/src/config/__tests__/index.test.ts +97 -0
- package/templates/apps/api/src/config/index.ts +56 -0
- package/templates/apps/api/src/index.ts +32 -0
- package/templates/apps/api/src/lib/__mocks__/prisma-client.js +15 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +45 -0
- package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +178 -0
- package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +100 -0
- package/templates/apps/api/src/lib/__tests__/errors.test.ts +94 -0
- package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +144 -0
- package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +8 -0
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +227 -0
- package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +125 -0
- package/templates/apps/api/src/lib/__tests__/prisma.test.ts +165 -0
- package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +129 -0
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +74 -0
- package/templates/apps/api/src/lib/content-adapter.ts +86 -0
- package/templates/apps/api/src/lib/error-serializer.ts +77 -0
- package/templates/apps/api/src/lib/errors.ts +95 -0
- package/templates/apps/api/src/lib/file-fallback.ts +87 -0
- package/templates/apps/api/src/lib/lead-capture-store.ts +110 -0
- package/templates/apps/api/src/lib/locales.ts +201 -0
- package/templates/apps/api/src/lib/outbound-http.ts +122 -0
- package/templates/apps/api/src/lib/prisma.ts +21 -0
- package/templates/apps/api/src/lib/require-paid-tier.ts +53 -0
- package/templates/apps/api/src/lib/stripe.ts +30 -0
- package/templates/apps/api/src/lib/webhook-idempotency.ts +92 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +111 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +172 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +119 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +138 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +149 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +139 -0
- package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +175 -0
- package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +76 -0
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +153 -0
- package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +72 -0
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +292 -0
- package/templates/apps/api/src/middleware/auth.ts +246 -0
- package/templates/apps/api/src/middleware/rate-limit.ts +132 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +129 -0
- package/templates/apps/api/src/openapi/index.ts +12 -0
- package/templates/apps/api/src/openapi/spec.ts +408 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +193 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +201 -0
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +294 -0
- package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +486 -0
- package/templates/apps/api/src/routes/auth/tokens.ts +199 -0
- package/templates/apps/api/src/routes/auth/user.ts +244 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +588 -0
- package/templates/apps/api/src/routes/checkout/index.ts +13 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +185 -0
- package/templates/apps/api/src/routes/content/__tests__/create.test.ts +239 -0
- package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +201 -0
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +141 -0
- package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +122 -0
- package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +44 -0
- package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +118 -0
- package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +51 -0
- package/templates/apps/api/src/routes/content/__tests__/update.test.ts +252 -0
- package/templates/apps/api/src/routes/content/create.ts +114 -0
- package/templates/apps/api/src/routes/content/delete.ts +81 -0
- package/templates/apps/api/src/routes/content/get-page.ts +98 -0
- package/templates/apps/api/src/routes/content/index.ts +32 -0
- package/templates/apps/api/src/routes/content/list-pages.ts +83 -0
- package/templates/apps/api/src/routes/content/list-types.ts +19 -0
- package/templates/apps/api/src/routes/content/rate-limit.ts +13 -0
- package/templates/apps/api/src/routes/content/slug.ts +9 -0
- package/templates/apps/api/src/routes/content/update.ts +111 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +415 -0
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +165 -0
- package/templates/apps/api/src/routes/leads/index.ts +130 -0
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +296 -0
- package/templates/apps/api/src/routes/test/auth/session.ts +141 -0
- package/templates/apps/api/src/routes/webhooks/README.md +57 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +247 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +198 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +633 -0
- package/templates/apps/api/src/routes/webhooks/index.ts +41 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +253 -0
- package/templates/apps/api/src/server.ts +157 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +395 -0
- package/templates/apps/api/src/services/enrichment-shim.ts +53 -0
- package/templates/apps/api/src/services/lead-routing.ts +338 -0
- package/templates/apps/api/tsconfig.json +34 -0
- package/templates/apps/api/vercel.json +17 -0
- package/templates/apps/mcp/.env.example +52 -0
- package/templates/apps/mcp/CLAUDE.md +84 -0
- package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +52 -0
- package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +46 -0
- package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +36 -0
- package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +54 -0
- package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +110 -0
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +213 -0
- package/templates/apps/mcp/__tests__/audit.test.ts +217 -0
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +52 -0
- package/templates/apps/mcp/__tests__/create_page.test.ts +201 -0
- package/templates/apps/mcp/__tests__/delete_page.test.ts +176 -0
- package/templates/apps/mcp/__tests__/get_business_hours.test.ts +82 -0
- package/templates/apps/mcp/__tests__/get_faq.test.ts +80 -0
- package/templates/apps/mcp/__tests__/get_locations.test.ts +65 -0
- package/templates/apps/mcp/__tests__/get_offerings.test.ts +90 -0
- package/templates/apps/mcp/__tests__/get_pricing.test.ts +80 -0
- package/templates/apps/mcp/__tests__/get_site_info.test.ts +81 -0
- package/templates/apps/mcp/__tests__/http-transport.test.ts +323 -0
- package/templates/apps/mcp/__tests__/lib/errors.test.ts +75 -0
- package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +75 -0
- package/templates/apps/mcp/__tests__/list_pages.test.ts +112 -0
- package/templates/apps/mcp/__tests__/locale.test.ts +135 -0
- package/templates/apps/mcp/__tests__/parity.test.ts +205 -0
- package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +34 -0
- package/templates/apps/mcp/__tests__/read_content.test.ts +153 -0
- package/templates/apps/mcp/__tests__/request_callback.test.ts +163 -0
- package/templates/apps/mcp/__tests__/search_content.test.ts +153 -0
- package/templates/apps/mcp/__tests__/server.test.ts +115 -0
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +165 -0
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +161 -0
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +227 -0
- package/templates/apps/mcp/__tests__/tools/scaffold.test.ts +237 -0
- package/templates/apps/mcp/__tests__/update_page.test.ts +195 -0
- package/templates/apps/mcp/jest.config.cjs +82 -0
- package/templates/apps/mcp/package.json +37 -0
- package/templates/apps/mcp/src/abuse/daily-cap.ts +47 -0
- package/templates/apps/mcp/src/abuse/email-validator.ts +25 -0
- package/templates/apps/mcp/src/abuse/honeypot.ts +21 -0
- package/templates/apps/mcp/src/abuse/index.ts +111 -0
- package/templates/apps/mcp/src/abuse/user-agent-deny.ts +58 -0
- package/templates/apps/mcp/src/http-transport.ts +303 -0
- package/templates/apps/mcp/src/index.ts +67 -0
- package/templates/apps/mcp/src/lib/audit-single-page.ts +194 -0
- package/templates/apps/mcp/src/lib/errors.ts +61 -0
- package/templates/apps/mcp/src/lib/locales.ts +171 -0
- package/templates/apps/mcp/src/lib/require-paid-tier.ts +44 -0
- package/templates/apps/mcp/src/lib/resolve-locale.ts +30 -0
- package/templates/apps/mcp/src/server.ts +139 -0
- package/templates/apps/mcp/src/tools/audit.ts +103 -0
- package/templates/apps/mcp/src/tools/capture_lead.ts +52 -0
- package/templates/apps/mcp/src/tools/create_page.ts +95 -0
- package/templates/apps/mcp/src/tools/delete_page.ts +73 -0
- package/templates/apps/mcp/src/tools/get_business_hours.ts +66 -0
- package/templates/apps/mcp/src/tools/get_faq.ts +69 -0
- package/templates/apps/mcp/src/tools/get_locations.ts +85 -0
- package/templates/apps/mcp/src/tools/get_offerings.ts +66 -0
- package/templates/apps/mcp/src/tools/get_pricing.ts +74 -0
- package/templates/apps/mcp/src/tools/get_site_info.ts +84 -0
- package/templates/apps/mcp/src/tools/index.ts +125 -0
- package/templates/apps/mcp/src/tools/list_pages.ts +72 -0
- package/templates/apps/mcp/src/tools/purchase.ts +89 -0
- package/templates/apps/mcp/src/tools/read_content.ts +61 -0
- package/templates/apps/mcp/src/tools/request_callback.ts +51 -0
- package/templates/apps/mcp/src/tools/scaffold.ts +119 -0
- package/templates/apps/mcp/src/tools/search_content.ts +59 -0
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +47 -0
- package/templates/apps/mcp/src/tools/update_page.ts +91 -0
- package/templates/apps/mcp/tsconfig.json +19 -0
- package/templates/apps/web/.env.example +47 -0
- package/templates/apps/web/CLAUDE.md +81 -0
- package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +94 -0
- package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +75 -0
- package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +82 -0
- package/templates/apps/web/__tests__/auth/env-helpers.test.ts +168 -0
- package/templates/apps/web/__tests__/authority-list-routes.test.tsx +208 -0
- package/templates/apps/web/__tests__/better-stack.test.ts +66 -0
- package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +87 -0
- package/templates/apps/web/__tests__/blog-source-populated.test.ts +130 -0
- package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +60 -0
- package/templates/apps/web/__tests__/google-analytics.test.tsx +104 -0
- package/templates/apps/web/__tests__/i18n/middleware.test.ts +119 -0
- package/templates/apps/web/__tests__/i18n/routing.test.ts +114 -0
- package/templates/apps/web/__tests__/i18n/translations.test.ts +191 -0
- package/templates/apps/web/__tests__/json-ld.test.ts +98 -0
- package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +580 -0
- package/templates/apps/web/__tests__/layout-stealth.test.ts +39 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +103 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +114 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +94 -0
- package/templates/apps/web/__tests__/page.test.tsx +230 -0
- package/templates/apps/web/__tests__/products-services-phase1.test.tsx +321 -0
- package/templates/apps/web/__tests__/projects-routes.test.tsx +392 -0
- package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +475 -0
- package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +53 -0
- package/templates/apps/web/__tests__/routes/blog-route.test.tsx +191 -0
- package/templates/apps/web/__tests__/routes/llms-txt.test.ts +123 -0
- package/templates/apps/web/__tests__/routes/robots-txt.test.ts +52 -0
- package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +78 -0
- package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +203 -0
- package/templates/apps/web/__tests__/section-routes.test.tsx +693 -0
- package/templates/apps/web/__tests__/security-headers.test.ts +201 -0
- package/templates/apps/web/__tests__/sentry-config.test.ts +116 -0
- package/templates/apps/web/__tests__/setup.ts +82 -0
- package/templates/apps/web/__tests__/sitemap-locales.test.ts +415 -0
- package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +844 -0
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +81 -0
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +110 -0
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +58 -0
- package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +120 -0
- package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +202 -0
- package/templates/apps/web/app/[locale]/about/page.tsx +31 -0
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +173 -0
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +45 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/careers/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +113 -0
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/clients/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +130 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +152 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +92 -0
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +79 -0
- package/templates/apps/web/app/[locale]/contact/error.tsx +24 -0
- package/templates/apps/web/app/[locale]/contact/page.tsx +38 -0
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +119 -0
- package/templates/apps/web/app/[locale]/courses/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/dev/purchase/__tests__/actions.test.ts +160 -0
- package/templates/apps/web/app/[locale]/dev/purchase/error.tsx +25 -0
- package/templates/apps/web/app/[locale]/dev/purchase/page.tsx +117 -0
- package/templates/apps/web/app/[locale]/dev/purchase/purchase.actions.ts +58 -0
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +118 -0
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +72 -0
- package/templates/apps/web/app/[locale]/downloads/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +47 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +130 -0
- package/templates/apps/web/app/[locale]/events/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/faq/page.tsx +36 -0
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +78 -0
- package/templates/apps/web/app/[locale]/how-to/page.tsx +40 -0
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/integrations/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/launch-service/page.tsx +31 -0
- package/templates/apps/web/app/[locale]/layout.tsx +241 -0
- package/templates/apps/web/app/[locale]/page.tsx +41 -0
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +113 -0
- package/templates/apps/web/app/[locale]/partners/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/products/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +138 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +30 -0
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +51 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/resources/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/services/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +81 -0
- package/templates/apps/web/app/[locale]/software/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +82 -0
- package/templates/apps/web/app/[locale]/tech-articles/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/testimonials/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +82 -0
- package/templates/apps/web/app/[locale]/whitepapers/page.tsx +39 -0
- package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +152 -0
- package/templates/apps/web/app/api/auth/[...all]/route.ts +16 -0
- package/templates/apps/web/app/error-fallback.tsx +75 -0
- package/templates/apps/web/app/error.tsx +23 -0
- package/templates/apps/web/app/layout.tsx +18 -0
- package/templates/apps/web/app/llms.txt/route.ts +101 -0
- package/templates/apps/web/app/not-found.tsx +48 -0
- package/templates/apps/web/app/og/__tests__/route.test.ts +164 -0
- package/templates/apps/web/app/og/route.tsx +135 -0
- package/templates/apps/web/app/robots.txt/route.ts +36 -0
- package/templates/apps/web/app/sitemap.xml/route.ts +146 -0
- package/templates/apps/web/auth.ts +141 -0
- package/templates/apps/web/components/ThemeToggle.tsx +60 -0
- package/templates/apps/web/components/google-analytics.tsx +34 -0
- package/templates/apps/web/content/en/blog/index.mdx +15 -0
- package/templates/apps/web/content/en/blog/launching-ailk.mdx +20 -0
- package/templates/apps/web/content/en/docs/getting-started.mdx +30 -0
- package/templates/apps/web/i18n/request.ts +36 -0
- package/templates/apps/web/jest.config.cjs +100 -0
- package/templates/apps/web/lib/__mocks__/next-mdx-remote-rsc.js +12 -0
- package/templates/apps/web/lib/__mocks__/source-server.js +31 -0
- package/templates/apps/web/lib/__tests__/og.test.ts +65 -0
- package/templates/apps/web/lib/auth-env.ts +66 -0
- package/templates/apps/web/lib/blog-list-data.ts +95 -0
- package/templates/apps/web/lib/blog-post-data.ts +79 -0
- package/templates/apps/web/lib/nav-config.ts +13 -0
- package/templates/apps/web/lib/observability/better-stack.ts +27 -0
- package/templates/apps/web/lib/og.ts +23 -0
- package/templates/apps/web/lib/prisma-for-auth.ts +34 -0
- package/templates/apps/web/lib/source.ts +34 -0
- package/templates/apps/web/messages/en.json +131 -0
- package/templates/apps/web/middleware.ts +80 -0
- package/templates/apps/web/next.config.mjs +167 -0
- package/templates/apps/web/package.json +62 -0
- package/templates/apps/web/public/.well-known/security.txt +17 -0
- package/templates/apps/web/public/android-chrome-192x192.png +0 -0
- package/templates/apps/web/public/android-chrome-512x512.png +0 -0
- package/templates/apps/web/public/apple-touch-icon.png +0 -0
- package/templates/apps/web/public/favicon-16x16.png +0 -0
- package/templates/apps/web/public/favicon-32x32.png +0 -0
- package/templates/apps/web/public/favicon.ico +0 -0
- package/templates/apps/web/public/favicon.svg +4 -0
- package/templates/apps/web/public/logo-dark.svg +21 -0
- package/templates/apps/web/public/logo-light.svg +21 -0
- package/templates/apps/web/public/logomark-dark.svg +4 -0
- package/templates/apps/web/public/logomark-light.svg +4 -0
- package/templates/apps/web/public/og-default.png +0 -0
- package/templates/apps/web/public/site.webmanifest +19 -0
- package/templates/apps/web/scripts/assert-content-bundled.ts +55 -0
- package/templates/apps/web/security-headers.config.ts +132 -0
- package/templates/apps/web/sentry.client.config.ts +27 -0
- package/templates/apps/web/sentry.edge.config.ts +15 -0
- package/templates/apps/web/sentry.server.config.ts +20 -0
- package/templates/apps/web/source.config.ts +78 -0
- package/templates/apps/web/src/components/SiteNav.tsx +21 -0
- package/templates/apps/web/src/lib/routes.ts +37 -0
- package/templates/apps/web/tsconfig.json +35 -0
- package/templates/apps/web/types/messages.d.ts +19 -0
- package/templates/content/.gitkeep +0 -0
- package/templates/content/CLAUDE.md +85 -0
- package/templates/content/_site.mdx +38 -0
- package/templates/content/ar/HomePage/home.mdx +123 -0
- package/templates/content/ar/_site.mdx +35 -0
- package/templates/content/de/_site.mdx +29 -0
- package/templates/content/en/.gitkeep +0 -0
- package/templates/content/en/AboutPage/about.mdx +19 -0
- package/templates/content/en/AboutPage/about.schema.json +82 -0
- package/templates/content/en/BookCall/book-call.mdx +19 -0
- package/templates/content/en/BookCall/book-call.schema.json +121 -0
- package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +20 -0
- package/templates/content/en/CareersList/careers.mdx +24 -0
- package/templates/content/en/CaseStudiesList/case-studies.mdx +22 -0
- package/templates/content/en/CaseStudiesList/showcase.mdx +8 -0
- package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +32 -0
- package/templates/content/en/CaseStudy/schema-builder-migration.mdx +41 -0
- package/templates/content/en/ClientsList/clients.mdx +38 -0
- package/templates/content/en/ContactPage/contact.mdx +19 -0
- package/templates/content/en/ContactPage/contact.schema.json +100 -0
- package/templates/content/en/ContactPoint/primary.mdx +14 -0
- package/templates/content/en/Course/aeo-fundamentals.mdx +37 -0
- package/templates/content/en/Course/schema-builder-workshop.mdx +62 -0
- package/templates/content/en/CoursesList/courses.mdx +22 -0
- package/templates/content/en/DownloadsList/downloads.mdx +22 -0
- package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +39 -0
- package/templates/content/en/Event/ailk-launch-day-2026.mdx +35 -0
- package/templates/content/en/EventsList/events.mdx +26 -0
- package/templates/content/en/FAQPage/faq.mdx +420 -0
- package/templates/content/en/FAQPage/faq.schema.json +231 -0
- package/templates/content/en/GlossaryList/glossary.mdx +19 -0
- package/templates/content/en/GlossaryList/glossary.schema.json +300 -0
- package/templates/content/en/HomePage/home.mdx +312 -0
- package/templates/content/en/HomePage/home.schema.json +88 -0
- package/templates/content/en/HomePage/launch-service.mdx +475 -0
- package/templates/content/en/HomePage/launch-service.schema.json +138 -0
- package/templates/content/en/HowTo/add-mdx-content.mdx +38 -0
- package/templates/content/en/HowTo/configure-aeo-scoring.mdx +35 -0
- package/templates/content/en/HowTo/set-up-json-ld.mdx +36 -0
- package/templates/content/en/Integration/github-actions.mdx +31 -0
- package/templates/content/en/Integration/openai-api.mdx +26 -0
- package/templates/content/en/Integration/vercel.mdx +32 -0
- package/templates/content/en/IntegrationsList/integrations.mdx +22 -0
- package/templates/content/en/JobPosting/content-strategist.mdx +46 -0
- package/templates/content/en/JobPosting/developer-advocate.mdx +47 -0
- package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +57 -0
- package/templates/content/en/LandingPage/aeo-audit.mdx +19 -0
- package/templates/content/en/LandingPage/aeo-audit.schema.json +92 -0
- package/templates/content/en/LandingPage/agency-waitlist.mdx +340 -0
- package/templates/content/en/LandingPage/agency-waitlist.schema.json +152 -0
- package/templates/content/en/LandingPage/developers.mdx +19 -0
- package/templates/content/en/LandingPage/developers.schema.json +109 -0
- package/templates/content/en/LandingPage/for-agencies.mdx +390 -0
- package/templates/content/en/LandingPage/for-agencies.schema.json +107 -0
- package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +417 -0
- package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +105 -0
- package/templates/content/en/LandingPage/for-businesses.mdx +19 -0
- package/templates/content/en/LandingPage/for-businesses.schema.json +96 -0
- package/templates/content/en/LandingPage/platform.mdx +369 -0
- package/templates/content/en/LandingPage/platform.schema.json +166 -0
- package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +19 -0
- package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +102 -0
- package/templates/content/en/LandingPage/vs-wordpress.mdx +19 -0
- package/templates/content/en/LandingPage/vs-wordpress.schema.json +53 -0
- package/templates/content/en/NewsletterSignup/newsletter.mdx +236 -0
- package/templates/content/en/NewsletterSignup/newsletter.schema.json +91 -0
- package/templates/content/en/Organization/site-owner.mdx +16 -0
- package/templates/content/en/Partner/prisma.mdx +31 -0
- package/templates/content/en/Partner/supabase.mdx +30 -0
- package/templates/content/en/Partner/vercel.mdx +28 -0
- package/templates/content/en/PartnersList/partners.mdx +22 -0
- package/templates/content/en/Person/founder.mdx +18 -0
- package/templates/content/en/Pricing/pricing.mdx +538 -0
- package/templates/content/en/Pricing/pricing.schema.json +209 -0
- package/templates/content/en/PrivacyPage/privacy.mdx +165 -0
- package/templates/content/en/PrivacyPage/privacy.schema.json +64 -0
- package/templates/content/en/Product/ailk.mdx +19 -0
- package/templates/content/en/Product/ailk.schema.json +94 -0
- package/templates/content/en/Product/api-launch-kit.mdx +26 -0
- package/templates/content/en/Product/launch-kit.mdx +28 -0
- package/templates/content/en/ProductsList/products.mdx +26 -0
- package/templates/content/en/Project/ailk-phase-2.mdx +54 -0
- package/templates/content/en/ProjectsList/projects.mdx +25 -0
- package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +27 -0
- package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +28 -0
- package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +39 -0
- package/templates/content/en/ResourcesHub/resources.mdx +22 -0
- package/templates/content/en/Service/consulting.mdx +22 -0
- package/templates/content/en/Service/implementation.mdx +30 -0
- package/templates/content/en/Service/launch-service.mdx +232 -0
- package/templates/content/en/Service/launch.mdx +228 -0
- package/templates/content/en/ServicesList/services.mdx +84 -0
- package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +44 -0
- package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +47 -0
- package/templates/content/en/SoftwareProduct/ailk-schema.mdx +49 -0
- package/templates/content/en/TeamList/team.mdx +63 -0
- package/templates/content/en/TeamMember/founder.mdx +72 -0
- package/templates/content/en/TermsPage/terms.mdx +19 -0
- package/templates/content/en/TermsPage/terms.schema.json +99 -0
- package/templates/content/en/TestimonialsList/testimonials.mdx +44 -0
- package/templates/content/en/UseCasesList/use-cases.mdx +30 -0
- package/templates/content/en/Whitepaper/ax-first-product-development.mdx +27 -0
- package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +27 -0
- package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +31 -0
- package/templates/content/en-XA/AboutPage/about.mdx +8 -0
- package/templates/content/en-XA/FAQPage/faq.mdx +8 -0
- package/templates/content/en-XA/HomePage/home.mdx +8 -0
- package/templates/content/es/_site.mdx +30 -0
- package/templates/content/fr/_site.mdx +30 -0
- package/templates/content/ja/_site.mdx +30 -0
- package/templates/content/pt-BR/AboutPage/about.mdx +8 -0
- package/templates/content/pt-BR/FAQPage/faq.mdx +8 -0
- package/templates/content/pt-BR/HomePage/home.mdx +23 -0
- package/templates/database/CHANGELOG.md +5 -0
- package/templates/database/README.md +234 -0
- package/templates/database/__tests__/user-cascade.test.ts +125 -0
- package/templates/database/auth/.gitkeep +0 -0
- package/templates/database/config/.gitkeep +0 -0
- package/templates/database/content/.gitkeep +0 -0
- package/templates/database/inbox/.gitkeep +0 -0
- package/templates/database/inbox/README.md +3 -0
- package/templates/database/inbox/__tests__/schema.test.ts +40 -0
- package/templates/database/inbox/schema.prisma +52 -0
- package/templates/database/jest.config.cjs +29 -0
- package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +328 -0
- package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +100 -0
- package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +28 -0
- package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +25 -0
- package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +42 -0
- package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +67 -0
- package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +21 -0
- package/templates/database/migrations/migration_lock.toml +3 -0
- package/templates/database/ops/.gitkeep +0 -0
- package/templates/database/package.json +45 -0
- package/templates/database/prisma.config.ts +20 -0
- package/templates/database/schema.prisma +487 -0
- package/templates/database/scripts/db-generate-locked.sh +80 -0
- package/templates/database/seed-test.ts +85 -0
- package/templates/database/tsconfig.build.json +16 -0
- package/templates/database/tsconfig.json +9 -0
- package/templates/package.json +125 -0
- package/templates/pnpm-workspace.yaml +6 -0
- package/templates/project.yaml +59 -0
- package/templates/tsconfig.base.json +18 -0
- package/templates/tsconfig.json +45 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Emitted by `scaffold-commerce` (link path). Owns its own
|
|
2
|
+
// <MarketplaceCTA> component definition — not imported from
|
|
3
|
+
// @working-theory/ui — so you can edit the styling, add tracking, change
|
|
4
|
+
// the icon layout, etc., without forking a shared package.
|
|
5
|
+
//
|
|
6
|
+
// The skill substitutes:
|
|
7
|
+
// {{HREF}} — storefront URL (e.g., https://amazon.com/my-shop)
|
|
8
|
+
// {{LABEL}} — button text (e.g., "Buy on Amazon")
|
|
9
|
+
// {{ICON}} — optional iconSrc prop binding (e.g., iconSrc="/logos/amazon.svg")
|
|
10
|
+
// or empty when the consumer chose text-only
|
|
11
|
+
|
|
12
|
+
import type { ReactNode } from "react";
|
|
13
|
+
|
|
14
|
+
interface MarketplaceCTAProps {
|
|
15
|
+
href: string;
|
|
16
|
+
label: ReactNode;
|
|
17
|
+
iconSrc?: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* MarketplaceCTA — outbound link to an external storefront.
|
|
23
|
+
*
|
|
24
|
+
* Renders a single anchor styled as a button. Optional iconSrc renders
|
|
25
|
+
* a small <img> next to the label; omitting it produces a clean
|
|
26
|
+
* text-only button. Customize freely — this component is yours, not
|
|
27
|
+
* a shared dep.
|
|
28
|
+
*/
|
|
29
|
+
function MarketplaceCTA({
|
|
30
|
+
href,
|
|
31
|
+
label,
|
|
32
|
+
iconSrc,
|
|
33
|
+
className,
|
|
34
|
+
}: MarketplaceCTAProps) {
|
|
35
|
+
const baseClasses =
|
|
36
|
+
"inline-flex items-center gap-2 rounded-md border border-current px-4 py-2 text-sm font-medium hover:bg-current/5 transition-colors";
|
|
37
|
+
const finalClassName = className
|
|
38
|
+
? `${baseClasses} ${className}`
|
|
39
|
+
: baseClasses;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<a
|
|
43
|
+
href={href}
|
|
44
|
+
target="_blank"
|
|
45
|
+
rel="noopener noreferrer"
|
|
46
|
+
className={finalClassName}
|
|
47
|
+
>
|
|
48
|
+
{iconSrc ? (
|
|
49
|
+
<img src={iconSrc} alt="" aria-hidden="true" className="h-5 w-5" />
|
|
50
|
+
) : null}
|
|
51
|
+
<span>{label}</span>
|
|
52
|
+
</a>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default function BuyPage() {
|
|
57
|
+
return (
|
|
58
|
+
<main className="mx-auto max-w-2xl px-6 py-12">
|
|
59
|
+
<h1 className="text-3xl font-semibold">Get yours</h1>
|
|
60
|
+
<p className="mt-3 text-muted-foreground">
|
|
61
|
+
Available at our store on the marketplace below.
|
|
62
|
+
</p>
|
|
63
|
+
<div className="mt-8">
|
|
64
|
+
<MarketplaceCTA
|
|
65
|
+
href="{{HREF}}"
|
|
66
|
+
label="{{LABEL}}"
|
|
67
|
+
{{ICON}}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
</main>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scaffold-page
|
|
3
|
+
description: Generate a new page on an AILK consumer site — App Router route + MDX content stub + typed JSON-LD attachment — in a single confirm-before-write pass. Use when the user says "scaffold me a /pricing page", "add an about page", "create a /contact route", or chains a row from `suggest-site-pages` output (e.g., "scaffold home — Organization — anchor with hero, value prop, CTA"). Both invocation shapes flow through the same pipeline. MDX-only at v1; refuses on existing routes and points at `add-schema` (#366).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# scaffold-page
|
|
7
|
+
|
|
8
|
+
Generate a new page in one pass. Three artifacts emit together:
|
|
9
|
+
|
|
10
|
+
1. **App Router route** at `app/<slug>/page.tsx`
|
|
11
|
+
2. **MDX content stub** at `content/<Type>/<slug>.mdx`
|
|
12
|
+
3. **JSON-LD attachment** via `<JsonLd schema={build<Type>(page)} />` from
|
|
13
|
+
`@working-theory/jsonld` (component) and `@working-theory/schema` (typed builder)
|
|
14
|
+
|
|
15
|
+
Single confirm-before-write — no per-file or per-step prompts.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
The consumer wants a new page on their AILK site. Triggers:
|
|
20
|
+
|
|
21
|
+
- "scaffold me a /pricing page" / "create a /contact route"
|
|
22
|
+
- "add an about page" / "I need a /privacy page"
|
|
23
|
+
- A row chained from `suggest-site-pages` output:
|
|
24
|
+
`home — Organization — anchor with hero, value prop, CTA`
|
|
25
|
+
- "scaffold that one" referring to a specific row from prior chat output
|
|
26
|
+
|
|
27
|
+
Skip this skill when:
|
|
28
|
+
|
|
29
|
+
- The consumer wants to **add schema to an existing page** — that's
|
|
30
|
+
`add-schema` (#366). This skill refuses on existing routes and
|
|
31
|
+
points at #366 explicitly.
|
|
32
|
+
- The consumer wants to **plan their pages** — that's
|
|
33
|
+
`suggest-site-pages` (#361). Output of #361 is this skill's chained
|
|
34
|
+
input contract.
|
|
35
|
+
- The consumer's content backend is **not MDX**. v1 is MDX-only —
|
|
36
|
+
other adapters (Sanity, Payload, additional adapters) are additive
|
|
37
|
+
future PRs. Refuse with a clear message.
|
|
38
|
+
|
|
39
|
+
## What this skill does
|
|
40
|
+
|
|
41
|
+
1. Parses the consumer's input — chained format
|
|
42
|
+
(`<slug> — <Schema.orgType> — <purpose>`) OR free-text.
|
|
43
|
+
2. Resolves the **primary schema.org type** for the page using
|
|
44
|
+
`references/page-types.md` (about → AboutPage, pricing → Service,
|
|
45
|
+
etc.). Confirms the choice before writing.
|
|
46
|
+
3. Detects existing routes and refuses if `app/<slug>/page.tsx`
|
|
47
|
+
already exists, pointing at `add-schema` (#366).
|
|
48
|
+
4. Detects content adapter — only MDX is supported at v1; refuses
|
|
49
|
+
on any other adapter with a clear message.
|
|
50
|
+
5. Emits three files via `templates/route.tsx.tmpl` and
|
|
51
|
+
`templates/content.mdx.tmpl` (instantiated per page) plus a
|
|
52
|
+
typed builder import from `@working-theory/schema`.
|
|
53
|
+
6. Shows the consumer a **single diff** of all three files and waits
|
|
54
|
+
for one confirmation. After approval, writes all files.
|
|
55
|
+
7. Closing summary: pointer at `add-schema` (#366) for additional
|
|
56
|
+
schema, pointer at `audit-site` (#365) for citation-readiness check.
|
|
57
|
+
|
|
58
|
+
## What this skill does NOT do
|
|
59
|
+
|
|
60
|
+
- Modify an existing route. Refuses + points at `add-schema` (#366).
|
|
61
|
+
- Run `pnpm dev` or rebuild content. The consumer does that.
|
|
62
|
+
- Detect content-adapter type beyond "is it MDX?". v1 ships MDX
|
|
63
|
+
only; other adapters are out of scope.
|
|
64
|
+
- Use `<script type="application/ld+json">` blocks or
|
|
65
|
+
`generateMetadata.other`. The canonical attachment is always
|
|
66
|
+
`<JsonLd>` from `@working-theory/jsonld`.
|
|
67
|
+
- Hand-code JSON-LD object literals. The typed builder from
|
|
68
|
+
`@working-theory/schema` is the source of truth (e.g. `buildOrganization(...)`,
|
|
69
|
+
`buildHomePage(...)`).
|
|
70
|
+
|
|
71
|
+
## The mechanic
|
|
72
|
+
|
|
73
|
+
### Step 1 — Parse the input
|
|
74
|
+
|
|
75
|
+
The consumer's request can arrive in either shape:
|
|
76
|
+
|
|
77
|
+
**Chained shape** (from `suggest-site-pages` output):
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
home — Organization — anchor with hero, value prop, CTA
|
|
81
|
+
about — AboutPage — company story and team
|
|
82
|
+
pricing — Service — public price tiers and feature comparison
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Three em-dash-separated fields: `<slug>` `<Schema.orgType>` `<purpose>`.
|
|
86
|
+
|
|
87
|
+
**Free-text shape:**
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
"scaffold me a /pricing page"
|
|
91
|
+
"add an about page"
|
|
92
|
+
"create a /contact route for sales"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Both shapes resolve to the same internal triple: `(slug, type, purpose)`.
|
|
96
|
+
|
|
97
|
+
For free-text:
|
|
98
|
+
|
|
99
|
+
- Extract the slug from the URL-shaped fragment ("/pricing" → "pricing"; "an about page" → "about").
|
|
100
|
+
- Resolve the `type` from `references/page-types.md` (the slug is the lookup key).
|
|
101
|
+
- The `purpose` is whatever description the consumer gave — used as MDX `description` frontmatter.
|
|
102
|
+
|
|
103
|
+
If you can't resolve a slug → type from the references file, **ask the consumer** rather than guessing. Don't fabricate types.
|
|
104
|
+
|
|
105
|
+
### Step 2 — Detect MDX adapter
|
|
106
|
+
|
|
107
|
+
Quick check: does the consumer's project have an MDX content
|
|
108
|
+
backend?
|
|
109
|
+
|
|
110
|
+
- Look for `content/` directory at the project root.
|
|
111
|
+
- Look for `apps/web/source.config.ts` or `next.config.ts` that
|
|
112
|
+
references `@working-theory/content-adapters` MDX adapter.
|
|
113
|
+
|
|
114
|
+
If neither exists, refuse:
|
|
115
|
+
|
|
116
|
+
> "scaffold-page only supports the MDX content backend at v1. Your
|
|
117
|
+
> project doesn't appear to have one — file an issue at the upstream
|
|
118
|
+
> repo if you'd like Sanity / Payload / additional adapter support."
|
|
119
|
+
|
|
120
|
+
Stop. No writes.
|
|
121
|
+
|
|
122
|
+
### Step 3 — Detect existing route
|
|
123
|
+
|
|
124
|
+
Check for `apps/web/app/<slug>/page.tsx` (or `app/<slug>/page.tsx`
|
|
125
|
+
depending on the consumer's structure).
|
|
126
|
+
|
|
127
|
+
If it exists, refuse:
|
|
128
|
+
|
|
129
|
+
> "A route at `/<slug>` already exists. To **add schema** to an
|
|
130
|
+
> existing page, run `add-schema` (#366) instead. To **replace** the
|
|
131
|
+
> page entirely, delete the existing files first and re-run this
|
|
132
|
+
> skill."
|
|
133
|
+
|
|
134
|
+
Stop. No writes.
|
|
135
|
+
|
|
136
|
+
### Step 4 — Instantiate the templates
|
|
137
|
+
|
|
138
|
+
Use `templates/route.tsx.tmpl` and `templates/content.mdx.tmpl` as
|
|
139
|
+
sources. Substitute:
|
|
140
|
+
|
|
141
|
+
| Placeholder | Source |
|
|
142
|
+
| ----------------- | -------------------------------------------------- |
|
|
143
|
+
| `{{SLUG}}` | from Step 1 (e.g., `pricing`) |
|
|
144
|
+
| `{{TYPE}}` | from Step 1 (e.g., `Service`) |
|
|
145
|
+
| `{{TYPE_KEBAB}}` | type lowercased + kebab (e.g., `service`) |
|
|
146
|
+
| `{{TYPE_CAMEL}}` | type camelCased for builder name (e.g., `service`) |
|
|
147
|
+
| `{{BUILDER}}` | builder function name (e.g., `buildService`) |
|
|
148
|
+
| `{{TITLE}}` | derived from slug, title-cased (e.g., "Pricing") |
|
|
149
|
+
| `{{DESCRIPTION}}` | the `purpose` field from input |
|
|
150
|
+
|
|
151
|
+
Builder name resolution: every type in `references/page-types.md`
|
|
152
|
+
maps to a `build<Type>` export from `@working-theory/schema`. Verify the
|
|
153
|
+
builder exists in the consumer's installed `@working-theory/schema` (check
|
|
154
|
+
`node_modules/@working-theory/schema/dist/index.d.ts` or its README) before
|
|
155
|
+
emitting the import. If the builder is missing, surface a clear
|
|
156
|
+
"`@working-theory/schema` doesn't export `build<Type>` yet — file an issue
|
|
157
|
+
upstream" message and stop.
|
|
158
|
+
|
|
159
|
+
### Step 5 — Show the diff
|
|
160
|
+
|
|
161
|
+
Present all three files (route + MDX + import path) in one
|
|
162
|
+
combined diff message. Single confirmation question:
|
|
163
|
+
|
|
164
|
+
> "I'll create:
|
|
165
|
+
>
|
|
166
|
+
> - `app/<slug>/page.tsx` (App Router route, ~30 lines)
|
|
167
|
+
> - `content/<Type>/<slug>.mdx` (content stub with frontmatter)
|
|
168
|
+
>
|
|
169
|
+
> The route imports `<JsonLd>` from `@working-theory/jsonld` and `build<Type>` from
|
|
170
|
+
> `@working-theory/schema`. JSON-LD is rendered server-side from the MDX
|
|
171
|
+
> frontmatter via the typed builder.
|
|
172
|
+
>
|
|
173
|
+
> Confirm to write all three files, or tell me what to change."
|
|
174
|
+
|
|
175
|
+
Wait for the consumer's confirmation. Do not write per-step.
|
|
176
|
+
|
|
177
|
+
### Step 6 — Write all three files
|
|
178
|
+
|
|
179
|
+
After confirmation, write the route file and MDX stub atomically.
|
|
180
|
+
The third "file" is the import line inside the route — already
|
|
181
|
+
included in the route template.
|
|
182
|
+
|
|
183
|
+
### Step 7 — Closing summary
|
|
184
|
+
|
|
185
|
+
Print:
|
|
186
|
+
|
|
187
|
+
- The two paths written.
|
|
188
|
+
- Reminder: `pnpm dev` to see the page, `pnpm build` to confirm it
|
|
189
|
+
compiles.
|
|
190
|
+
- Pointer at `add-schema` (#366) for adding supplementary schema
|
|
191
|
+
(FAQPage, HowTo, Product, etc.) to this page later.
|
|
192
|
+
- Pointer at `audit-site` (#365) for citation-readiness check after
|
|
193
|
+
adding pages.
|
|
194
|
+
|
|
195
|
+
## Cross-skill chaining
|
|
196
|
+
|
|
197
|
+
Output of `suggest-site-pages` (#361) is this skill's input contract.
|
|
198
|
+
The consumer can paste any row of #361's output verbatim and this
|
|
199
|
+
skill scaffolds it. Example end-to-end:
|
|
200
|
+
|
|
201
|
+
1. Consumer asks `suggest-site-pages` for a SaaS page list.
|
|
202
|
+
2. Output includes: `pricing — Service — public price tiers and feature comparison`
|
|
203
|
+
3. Consumer says: "scaffold that pricing one"
|
|
204
|
+
4. This skill resolves the row, emits route + MDX + JSON-LD, all in
|
|
205
|
+
one confirm-before-write pass.
|
|
206
|
+
5. Consumer continues with the next row, or moves on.
|
|
207
|
+
|
|
208
|
+
## What lives in `references/page-types.md`
|
|
209
|
+
|
|
210
|
+
The type-to-schema mapping is data, not logic. Read the references
|
|
211
|
+
file at runtime — don't try to remember the table.
|
|
212
|
+
|
|
213
|
+
The mapping covers the canonical AILK page types:
|
|
214
|
+
|
|
215
|
+
- Identity — `home → HomePage`, `about → AboutPage`
|
|
216
|
+
- Conversion — `pricing → Service`, `contact → ContactPage`
|
|
217
|
+
- Trust — `privacy → PrivacyPage`, `terms → TermsPage`
|
|
218
|
+
- Editorial — `blog → Blog`, `blog/<slug> → BlogPosting`
|
|
219
|
+
- Catalog — `products → ItemList`, `products/<slug> → Product`
|
|
220
|
+
- Q&A — `faq → FAQPage`, `how-to/<slug> → HowTo`
|
|
221
|
+
|
|
222
|
+
The full list is in `references/page-types.md`. New types added to
|
|
223
|
+
`@working-theory/schema` should be added to that file in a follow-up PR; the
|
|
224
|
+
skill renders unrecognized types as a "missing from page-types.md"
|
|
225
|
+
prompt to ask the consumer rather than guessing.
|
|
226
|
+
|
|
227
|
+
## Coordination
|
|
228
|
+
|
|
229
|
+
- **`suggest-site-pages` (#361)** — output is this skill's chained
|
|
230
|
+
input. The two skills' references corpora (`categories.md` and
|
|
231
|
+
`page-types.md`) must agree on schema-type names.
|
|
232
|
+
- **`add-schema` (#366)** — modifies existing pages. The
|
|
233
|
+
`<JsonLd schema={build<Type>(...)} />` attachment pattern is
|
|
234
|
+
shared with this skill (canonical pattern landed in #389 /
|
|
235
|
+
`@working-theory/jsonld`).
|
|
236
|
+
- **`audit-site` (#365)** — citation-readiness check. Runs after
|
|
237
|
+
pages exist; not invoked from inside this skill.
|
|
238
|
+
- **`@working-theory/jsonld`** (#389) — the React component for JSON-LD
|
|
239
|
+
rendering. Single source of truth for the attachment pattern.
|
|
240
|
+
- **`@working-theory/schema`** — typed builders (`buildHomePage`,
|
|
241
|
+
`buildAboutPage`, etc.). The skill's emit imports from here.
|
|
242
|
+
- **`@working-theory/content-adapters`** (MDX) — the content backend. v1 is
|
|
243
|
+
MDX-only; other adapters are deferred.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Page-Type → schema.org Mapping
|
|
2
|
+
|
|
3
|
+
The lookup table the `scaffold-page` skill reads at runtime to
|
|
4
|
+
resolve a slug or page-purpose hint to a primary schema.org `@type`
|
|
5
|
+
plus the matching `@working-theory/schema` builder name.
|
|
6
|
+
|
|
7
|
+
The skill resolves in this order:
|
|
8
|
+
|
|
9
|
+
1. **Exact slug match** — `pricing` → `Service`.
|
|
10
|
+
2. **Slug-prefix match** — `blog/<anything>` → `BlogPosting`.
|
|
11
|
+
3. **Free-text hint match** — "company story" / "team" → `AboutPage`.
|
|
12
|
+
4. **Ask** — if nothing matches, ask the consumer rather than
|
|
13
|
+
guessing.
|
|
14
|
+
|
|
15
|
+
This file's table must agree with the entries
|
|
16
|
+
`suggest-site-pages` (#361) emits in `categories.md`. When new types
|
|
17
|
+
land in `@working-theory/schema`, both files update in the same follow-up PR.
|
|
18
|
+
|
|
19
|
+
## Identity / surface pages
|
|
20
|
+
|
|
21
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
22
|
+
| ------- | --------------- | ---------------- | --------------------------------------------------------------------- |
|
|
23
|
+
| `home` | `HomePage` | `buildHomePage` | The site's root landing page. Anchors hero, value prop, primary CTAs. |
|
|
24
|
+
| `about` | `AboutPage` | `buildAboutPage` | Company story / team / founders. Trust + narrative. |
|
|
25
|
+
|
|
26
|
+
## Conversion pages
|
|
27
|
+
|
|
28
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
29
|
+
| --------- | --------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `pricing` | `Service` | `buildService` | Public price tiers and feature comparison. (Or `Product` if the consumer sells discrete physical/digital products with SKUs.) |
|
|
31
|
+
| `contact` | `ContactPage` | `buildContactPage` | Sales / support entry point. Form, address, hours. |
|
|
32
|
+
| `book` | `Reservation` | _consumer-defined_ | Service businesses with appointment booking (salon, contractor, restaurant table). Requires consumer to wire the reservation flow. |
|
|
33
|
+
|
|
34
|
+
## Trust pages
|
|
35
|
+
|
|
36
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
37
|
+
| --------- | --------------- | ------------------ | ----------------- |
|
|
38
|
+
| `privacy` | `PrivacyPage` | `buildPrivacyPage` | Privacy policy. |
|
|
39
|
+
| `terms` | `TermsPage` | `buildTermsPage` | Terms of service. |
|
|
40
|
+
|
|
41
|
+
## Editorial / blog
|
|
42
|
+
|
|
43
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
44
|
+
| ------------- | --------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| `blog` | `Blog` | _consumer-defined_ | Blog index page. Lists posts. |
|
|
46
|
+
| `blog/<slug>` | `BlogPosting` | _consumer-defined_ | Individual blog post. The skill's chained input handles the per-post case naturally — ask `scaffold-page` per post. |
|
|
47
|
+
|
|
48
|
+
> Builder availability for editorial types depends on `@working-theory/schema`
|
|
49
|
+
> exports at the consumer's installed version. If
|
|
50
|
+
> `buildBlogPosting` is missing, fall back to manually authoring
|
|
51
|
+
> the JSON-LD via `<JsonLd schema={{...}} />`.
|
|
52
|
+
|
|
53
|
+
## Catalog / commerce
|
|
54
|
+
|
|
55
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
56
|
+
| ----------------- | --------------- | ------------------ | ----------------------------------------------------- |
|
|
57
|
+
| `products` | `ItemList` | _consumer-defined_ | Product index. Lists products. |
|
|
58
|
+
| `products/<slug>` | `Product` | _consumer-defined_ | Individual product page. |
|
|
59
|
+
| `services` | `ServicesList` | _consumer-defined_ | Service index for service-business consumer profiles. |
|
|
60
|
+
| `services/<slug>` | `Service` | `buildService` | Individual service page. |
|
|
61
|
+
|
|
62
|
+
> For commerce wiring (Stripe products + lookup_keys), use
|
|
63
|
+
> `scaffold-commerce` (#363). This skill emits the page; commerce
|
|
64
|
+
> wires it.
|
|
65
|
+
|
|
66
|
+
## Q&A / how-to
|
|
67
|
+
|
|
68
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
69
|
+
| --------------- | --------------- | ------------------ | -------------------------------- |
|
|
70
|
+
| `faq` | `FAQPage` | _consumer-defined_ | Frequently-asked-questions page. |
|
|
71
|
+
| `how-to/<slug>` | `HowTo` | _consumer-defined_ | Step-by-step instructions page. |
|
|
72
|
+
|
|
73
|
+
## Real estate / listings
|
|
74
|
+
|
|
75
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
76
|
+
| ----------------- | ------------------- | ------------------ | ----------------------------- |
|
|
77
|
+
| `listings` | `ItemList` | _consumer-defined_ | Property index. |
|
|
78
|
+
| `listings/<slug>` | `RealEstateListing` | _consumer-defined_ | Individual listing. |
|
|
79
|
+
| `agent` | `RealEstateAgent` | _consumer-defined_ | Solo realtor / agent profile. |
|
|
80
|
+
|
|
81
|
+
## Healthcare / medical
|
|
82
|
+
|
|
83
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
84
|
+
| ----------------- | ------------------------------ | ------------------ | ------------------------------------------------- |
|
|
85
|
+
| `practice` | `MedicalBusiness` | _consumer-defined_ | Practice / clinic landing. |
|
|
86
|
+
| `provider` | `Physician` / `Dentist` / etc. | _consumer-defined_ | Solo provider profile. Type depends on specialty. |
|
|
87
|
+
| `services/<slug>` | `MedicalProcedure` | _consumer-defined_ | Procedure / treatment page. |
|
|
88
|
+
|
|
89
|
+
## Course / education
|
|
90
|
+
|
|
91
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
92
|
+
| ---------------- | ------------------ | ------------------ | --------------------- |
|
|
93
|
+
| `courses` | `ItemList` | _consumer-defined_ | Course catalog. |
|
|
94
|
+
| `courses/<slug>` | `Course` | _consumer-defined_ | Individual course. |
|
|
95
|
+
| `lesson/<slug>` | `LearningResource` | _consumer-defined_ | Free / sample lesson. |
|
|
96
|
+
|
|
97
|
+
## Nonprofit / org
|
|
98
|
+
|
|
99
|
+
| Slug | Primary `@type` | Builder | When to pick |
|
|
100
|
+
| ----------------- | --------------- | ------------------ | -------------------------------- |
|
|
101
|
+
| `mission` | `AboutPage` | `buildAboutPage` | Mission statement / what we do. |
|
|
102
|
+
| `donate` | `DonateAction` | _consumer-defined_ | Donation page. |
|
|
103
|
+
| `programs/<slug>` | `Program` | _consumer-defined_ | Individual program / initiative. |
|
|
104
|
+
|
|
105
|
+
## Identity entity (Organization vs Person)
|
|
106
|
+
|
|
107
|
+
The site's **identity entity** is emitted on `home` (or in a layout
|
|
108
|
+
component). Two flavors:
|
|
109
|
+
|
|
110
|
+
| Site profile | Identity `@type` | Builder |
|
|
111
|
+
| ------------------ | ---------------- | ------------------- |
|
|
112
|
+
| Business / company | `Organization` | `buildOrganization` |
|
|
113
|
+
| Solo individual | `Person` | `buildPerson` |
|
|
114
|
+
|
|
115
|
+
For categories that admit both (real estate, healthcare,
|
|
116
|
+
professional services, course/education), `suggest-site-pages`
|
|
117
|
+
(#361) disambiguates Person vs Organization based on the consumer's
|
|
118
|
+
free-text. This skill receives the resolved type as part of the
|
|
119
|
+
chained input or asks if free-text is ambiguous.
|
|
120
|
+
|
|
121
|
+
## When a slug doesn't match anything above
|
|
122
|
+
|
|
123
|
+
Don't guess. Ask the consumer:
|
|
124
|
+
|
|
125
|
+
> "I don't have a default schema.org type mapped for `/<slug>`. Two
|
|
126
|
+
> options:
|
|
127
|
+
>
|
|
128
|
+
> - Tell me which schema.org `@type` to use (e.g., `WebPage`,
|
|
129
|
+
> `Article`, `Event`).
|
|
130
|
+
> - Skip JSON-LD on this page; I emit a vanilla route + MDX stub
|
|
131
|
+
> and you wire schema later via `add-schema` (#366).
|
|
132
|
+
>
|
|
133
|
+
> Which?"
|
|
134
|
+
|
|
135
|
+
## Generic fallbacks
|
|
136
|
+
|
|
137
|
+
For pages that don't match a specific category, two safe fallbacks:
|
|
138
|
+
|
|
139
|
+
- `WebPage` — the most generic schema.org `@type`. Always valid, low
|
|
140
|
+
citation value.
|
|
141
|
+
- `Article` — for editorial / longform content that isn't a blog
|
|
142
|
+
post specifically.
|
|
143
|
+
|
|
144
|
+
The `WebPage` fallback is the implicit default if the consumer
|
|
145
|
+
explicitly says "no schema" — emit the route + MDX without an
|
|
146
|
+
emitted `<JsonLd>` block; consumer can add later via #366.
|
|
147
|
+
|
|
148
|
+
## When `@working-theory/schema` doesn't yet export the builder
|
|
149
|
+
|
|
150
|
+
Some types in this table say `_consumer-defined_` for the builder
|
|
151
|
+
column. That means `@working-theory/schema` doesn't export a typed builder
|
|
152
|
+
for that type yet. The skill's behavior:
|
|
153
|
+
|
|
154
|
+
1. Surface the gap to the consumer:
|
|
155
|
+
|
|
156
|
+
> "`@working-theory/schema` doesn't export `build<Type>` yet. I can:
|
|
157
|
+
>
|
|
158
|
+
> - Emit the route with an inline JSON-LD object literal (less
|
|
159
|
+
> type-safe but works).
|
|
160
|
+
> - Skip JSON-LD on this page; you wire it via `add-schema`
|
|
161
|
+
> (#366) once the builder ships upstream.
|
|
162
|
+
> - File an upstream issue requesting the builder.
|
|
163
|
+
>
|
|
164
|
+
> Which?"
|
|
165
|
+
|
|
166
|
+
2. Wait for the consumer's choice. Don't fabricate a builder.
|
|
167
|
+
|
|
168
|
+
The fallback to inline literals is documented in `add-schema`
|
|
169
|
+
(#366) too — both skills handle this case the same way.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: {{TYPE}}
|
|
3
|
+
slug: {{SLUG}}
|
|
4
|
+
title: {{TITLE}}
|
|
5
|
+
description: {{DESCRIPTION}}
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# {{TITLE}}
|
|
9
|
+
|
|
10
|
+
{{DESCRIPTION}}
|
|
11
|
+
|
|
12
|
+
<!--
|
|
13
|
+
This is the MDX content stub emitted by `scaffold-page`.
|
|
14
|
+
The frontmatter is the source of truth for JSON-LD — the
|
|
15
|
+
`{{BUILDER}}(page)` call in `app/{{SLUG}}/page.tsx` reads it.
|
|
16
|
+
|
|
17
|
+
Edit this file freely:
|
|
18
|
+
- Add sections, prose, components imported from your project.
|
|
19
|
+
- Update `description` (it's used both as the meta description
|
|
20
|
+
and as input to the JSON-LD builder).
|
|
21
|
+
- Don't change `type` unless you also update the route's import
|
|
22
|
+
to match a different `@working-theory/schema` builder.
|
|
23
|
+
|
|
24
|
+
When you're happy with the page, run `audit-site` (#365) to see
|
|
25
|
+
how it scores on citation-readiness. Use `add-schema` (#366) to
|
|
26
|
+
add supplementary schema (FAQPage, HowTo, etc.) without
|
|
27
|
+
re-scaffolding.
|
|
28
|
+
-->
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Emitted by `scaffold-page` at `app/{{SLUG}}/page.tsx`. Substitutions:
|
|
2
|
+
// {{SLUG}} — page slug (e.g., "pricing")
|
|
3
|
+
// {{TYPE}} — schema.org @type (e.g., "Service")
|
|
4
|
+
// {{BUILDER}} — typed builder name (e.g., "buildService")
|
|
5
|
+
// {{TITLE}} — page title (e.g., "Pricing")
|
|
6
|
+
import { notFound } from "next/navigation";
|
|
7
|
+
|
|
8
|
+
import { JsonLd } from "@working-theory/jsonld";
|
|
9
|
+
import { {{BUILDER}} } from "@working-theory/schema";
|
|
10
|
+
import { mdxAdapter } from "@/lib/content";
|
|
11
|
+
|
|
12
|
+
export default async function {{TYPE}}Page() {
|
|
13
|
+
const page = await mdxAdapter.getPage("{{SLUG}}");
|
|
14
|
+
if (!page) return notFound();
|
|
15
|
+
|
|
16
|
+
const schema = {{BUILDER}}(page);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<main className="mx-auto max-w-3xl px-6 py-12">
|
|
20
|
+
<JsonLd schema={schema} />
|
|
21
|
+
<article className="prose dark:prose-invert">
|
|
22
|
+
<h1>{page.title}</h1>
|
|
23
|
+
{page.description ? <p className="lead">{page.description}</p> : null}
|
|
24
|
+
{/* Render MDX body via your project's MDX renderer of choice. */}
|
|
25
|
+
</article>
|
|
26
|
+
</main>
|
|
27
|
+
);
|
|
28
|
+
}
|