create-ailk 0.3.0 → 0.5.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/component-catalog.json +11939 -0
- package/component-catalog.md +176 -64
- package/dist/cli.js +48 -10
- package/dist/derive-architecture.js +5 -2
- package/dist/lib/extract-module-bundle.d.ts +88 -1
- package/dist/lib/extract-module-bundle.js +375 -80
- package/dist/lib/fetch-guard.d.ts +28 -0
- package/dist/lib/fetch-guard.js +101 -0
- package/dist/lib/fetch-module.js +4 -0
- package/dist/lib/fetch-template.d.ts +20 -0
- package/dist/lib/fetch-template.js +133 -0
- package/dist/lib/module-license-gate.d.ts +8 -0
- package/dist/lib/module-license-gate.js +12 -4
- package/dist/module-architecture.d.ts +116 -7
- package/dist/module-architecture.js +465 -94
- package/dist/parse-args.d.ts +8 -1
- package/dist/parse-args.js +49 -2
- package/dist/programmatic.d.ts +36 -1
- package/dist/programmatic.js +216 -5
- package/dist/site-chrome.d.ts +80 -0
- package/dist/site-chrome.js +135 -0
- package/dist/surfaces.d.ts +21 -6
- package/dist/surfaces.js +140 -23
- package/dist/template-manifest.d.ts +144 -0
- package/dist/template-manifest.js +337 -0
- package/dist/template-names.d.ts +41 -0
- package/dist/template-names.js +45 -0
- package/package.json +10 -2
- package/site-templates/_base/ailk-template.json +6 -0
- package/site-templates/_base/content/en/Pricing/pricing.mdx +169 -0
- package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +79 -0
- package/site-templates/_base/content/en/TermsPage/terms.mdx +80 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +331 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +393 -0
- package/site-templates/marketing-site/ailk-template.json +11 -0
- package/site-templates/marketing-site/content/en/blog/05-this-vc-morning-routine-will-make-you-super-annoying.mdx +36 -0
- package/site-templates/marketing-site/provenance.json +4 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +288 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +285 -0
- package/site-templates/marketing-site-free/ailk-template.json +9 -0
- package/site-templates/marketing-site-free/provenance.json +4 -0
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +271 -0
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +324 -0
- package/site-templates/minimalism-site/ailk-template.json +21 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-1.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-2.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-3.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-4.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-5.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-6.svg +7 -0
- package/site-templates/minimalism-site/assets/hero-backdrop.svg +17 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-1.svg +6 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-2.svg +6 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-3.svg +6 -0
- package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +110 -0
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +68 -0
- package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +57 -0
- package/site-templates/minimalism-site/content/en/HomePage/home.mdx +214 -0
- package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +77 -0
- package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +73 -0
- package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +52 -0
- package/site-templates/minimalism-site/content/en/Service/first-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/Service/second-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/Service/third-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/ServicesList/services.mdx +73 -0
- package/site-templates/minimalism-site/flows/referral.flow.json +71 -0
- package/site-templates/minimalism-site/provenance.json +4 -0
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +61 -0
- package/site-templates/saas-product/ailk-template.json +16 -0
- package/site-templates/saas-product/provenance.json +10 -0
- package/templates/.claude/skills/README.md +16 -25
- package/templates/.env.example +32 -7
- package/templates/.github/workflows/ci.yml +48 -0
- package/templates/README.md +3 -1
- package/templates/apps/api/CLAUDE.md +4 -1
- package/templates/apps/api/eslint.config.mjs +69 -0
- package/templates/apps/api/package.json +6 -2
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +6 -2
- package/templates/apps/api/src/__tests__/review-surface-registration.test.ts +167 -0
- package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +173 -0
- package/templates/apps/api/src/config/modules.ts +1 -1
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +3 -0
- package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +339 -0
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +108 -0
- package/templates/apps/api/src/middleware/default-tenant.ts +136 -0
- package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +171 -0
- package/templates/apps/api/src/routes/leads/list.ts +104 -0
- package/templates/apps/api/src/server.ts +122 -3
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +408 -0
- package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +329 -0
- package/templates/apps/api/src/services/default-tenant.ts +261 -0
- package/templates/apps/api/src/services/lead-promotion.ts +161 -0
- package/templates/apps/api/src/services/leads-inbox.ts +263 -0
- package/templates/apps/api/src/services/owner-workspaces.ts +132 -0
- package/templates/apps/mcp/CLAUDE.md +1 -1
- package/templates/apps/mcp/__tests__/parity.test.ts +2 -2
- package/templates/apps/mcp/__tests__/tools/{scaffold.test.ts → create_project.test.ts} +23 -23
- package/templates/apps/mcp/eslint.config.mjs +69 -0
- package/templates/apps/mcp/package.json +6 -2
- package/templates/apps/mcp/src/server.ts +2 -2
- package/templates/apps/mcp/src/tools/{scaffold.ts → create_project.ts} +3 -3
- package/templates/apps/mcp/src/tools/index.ts +2 -2
- package/templates/apps/web/.env.example +3 -3
- package/templates/apps/web/CLAUDE.md +2 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +4 -6
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +1 -1
- package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +181 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/components/LeadsTable.tsx +137 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +111 -0
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +1 -1
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +111 -0
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +65 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +1 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +6 -5
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +1 -1
- package/templates/apps/web/app/[locale]/layout.tsx +214 -17
- package/templates/apps/web/app/[locale]/pricing/page.tsx +40 -0
- package/templates/apps/web/app/[locale]/privacy/page.tsx +40 -0
- package/templates/apps/web/app/[locale]/terms/page.tsx +40 -0
- package/templates/apps/web/components/google-analytics.tsx +18 -1
- package/templates/apps/web/eslint.config.mjs +69 -0
- package/templates/apps/web/jest.config.cjs +12 -15
- package/templates/apps/web/lib/__tests__/server-api.test.ts +61 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +32 -5
- package/templates/apps/web/lib/nav-config.ts +27 -7
- package/templates/apps/web/lib/server-api.ts +29 -13
- package/templates/apps/web/lib/site-chrome.ts +29 -0
- package/templates/apps/web/lib/telemetry-scrub.ts +46 -0
- package/templates/apps/web/messages/en.json +86 -1
- package/templates/apps/web/next.config.mjs +20 -0
- package/templates/apps/web/package.json +6 -2
- package/templates/apps/web/sentry.client.config.ts +131 -0
- package/templates/apps/web/sentry.edge.config.ts +72 -0
- package/templates/apps/web/sentry.server.config.ts +72 -0
- package/templates/apps/web/src/lib/routes.ts +13 -18
- package/templates/brand_assets/README.md +24 -0
- package/templates/content/en/AboutPage/about.mdx +160 -15
- package/templates/content/en/ContactPage/contact.mdx +90 -13
- package/templates/content/en/FAQPage/faq.mdx +62 -22
- package/templates/content/en/HomePage/home.mdx +244 -20
- package/templates/content/en/LandingPage/blog.mdx +83 -0
- package/templates/content/en/LandingPage/features.mdx +103 -0
- package/templates/content/en/LandingPage/how-it-works.mdx +143 -0
- package/templates/database/CHANGELOG.md +21 -0
- package/templates/database/__tests__/seed.test.ts +1 -1
- package/templates/database/eslint.config.mjs +69 -0
- package/templates/database/package.json +7 -3
- package/templates/database/seed.ts +1 -1
- package/templates/package.json +1 -14
- package/versions.json +52 -0
- /package/templates/apps/web/{src/components → components}/SiteNav.tsx +0 -0
|
@@ -7,9 +7,81 @@
|
|
|
7
7
|
|
|
8
8
|
import * as Sentry from "@sentry/nextjs";
|
|
9
9
|
|
|
10
|
+
import { scrubTelemetryUrl } from "./lib/telemetry-scrub";
|
|
11
|
+
|
|
12
|
+
// #5613 / security review PR #5639: the report-grant token (?g=<id> on
|
|
13
|
+
// /reports/<slug>, #5562) is a bearer credential for a private customer
|
|
14
|
+
// deliverable and must never leave this app in a URL. The RSC render of the
|
|
15
|
+
// grant page can run in this runtime too, so scrub the request URL, its
|
|
16
|
+
// Referer header, the transaction name, navigation breadcrumbs, and any URL
|
|
17
|
+
// captured as span/trace data (e.g. `url.full`,
|
|
18
|
+
// `http.request.header.referer`) here as well.
|
|
19
|
+
function scrubSentryEvent<
|
|
20
|
+
T extends {
|
|
21
|
+
request?: { url?: string; headers?: Record<string, string> };
|
|
22
|
+
transaction?: string;
|
|
23
|
+
breadcrumbs?: { category?: string; data?: Record<string, unknown> }[];
|
|
24
|
+
contexts?: { trace?: { data?: Record<string, unknown> } };
|
|
25
|
+
spans?: { data?: Record<string, unknown> }[];
|
|
26
|
+
},
|
|
27
|
+
>(event: T): T {
|
|
28
|
+
if (event.request?.url) {
|
|
29
|
+
event.request.url = scrubTelemetryUrl(event.request.url);
|
|
30
|
+
}
|
|
31
|
+
if (event.request?.headers) {
|
|
32
|
+
for (const key of ["Referer", "referer"]) {
|
|
33
|
+
const value = event.request.headers[key];
|
|
34
|
+
if (typeof value === "string") {
|
|
35
|
+
event.request.headers[key] = scrubTelemetryUrl(value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (event.transaction) {
|
|
40
|
+
event.transaction = scrubTelemetryUrl(event.transaction);
|
|
41
|
+
}
|
|
42
|
+
for (const crumb of event.breadcrumbs ?? []) {
|
|
43
|
+
if (!crumb.data) continue;
|
|
44
|
+
if (crumb.category === "navigation") {
|
|
45
|
+
for (const key of ["to", "from"]) {
|
|
46
|
+
const value = crumb.data[key];
|
|
47
|
+
if (typeof value === "string") {
|
|
48
|
+
crumb.data[key] = scrubTelemetryUrl(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// fetch/xhr breadcrumbs (and others) can carry `data.url` independent
|
|
53
|
+
// of category — scrub it regardless (security review, PR #5639).
|
|
54
|
+
const url = crumb.data["url"];
|
|
55
|
+
if (typeof url === "string") {
|
|
56
|
+
crumb.data["url"] = scrubTelemetryUrl(url);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const scrubSpanData = (data?: Record<string, unknown>): void => {
|
|
60
|
+
if (!data) return;
|
|
61
|
+
for (const key of [
|
|
62
|
+
"url.full",
|
|
63
|
+
"http.url",
|
|
64
|
+
"http.request.header.referer",
|
|
65
|
+
]) {
|
|
66
|
+
const value = data[key];
|
|
67
|
+
if (typeof value === "string") {
|
|
68
|
+
data[key] = scrubTelemetryUrl(value);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
scrubSpanData(event.contexts?.trace?.data);
|
|
73
|
+
for (const span of event.spans ?? []) {
|
|
74
|
+
scrubSpanData(span.data);
|
|
75
|
+
}
|
|
76
|
+
return event;
|
|
77
|
+
}
|
|
78
|
+
|
|
10
79
|
Sentry.init({
|
|
11
80
|
dsn: process.env.SENTRY_DSN,
|
|
12
81
|
enabled: !!process.env.SENTRY_DSN,
|
|
13
82
|
|
|
14
83
|
tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
|
|
84
|
+
|
|
85
|
+
beforeSend: scrubSentryEvent,
|
|
86
|
+
beforeSendTransaction: scrubSentryEvent,
|
|
15
87
|
});
|
|
@@ -12,9 +12,81 @@
|
|
|
12
12
|
|
|
13
13
|
import * as Sentry from "@sentry/nextjs";
|
|
14
14
|
|
|
15
|
+
import { scrubTelemetryUrl } from "./lib/telemetry-scrub";
|
|
16
|
+
|
|
17
|
+
// #5613 / security review PR #5639: the report-grant token (?g=<id> on
|
|
18
|
+
// /reports/<slug>, #5562) is a bearer credential for a private customer
|
|
19
|
+
// deliverable and must never leave this app in a URL. The RSC render of the
|
|
20
|
+
// grant page runs in this runtime, so scrub the request URL, its Referer
|
|
21
|
+
// header, the transaction name, navigation breadcrumbs, and any URL
|
|
22
|
+
// captured as span/trace data (e.g. `url.full`,
|
|
23
|
+
// `http.request.header.referer`) here too.
|
|
24
|
+
function scrubSentryEvent<
|
|
25
|
+
T extends {
|
|
26
|
+
request?: { url?: string; headers?: Record<string, string> };
|
|
27
|
+
transaction?: string;
|
|
28
|
+
breadcrumbs?: { category?: string; data?: Record<string, unknown> }[];
|
|
29
|
+
contexts?: { trace?: { data?: Record<string, unknown> } };
|
|
30
|
+
spans?: { data?: Record<string, unknown> }[];
|
|
31
|
+
},
|
|
32
|
+
>(event: T): T {
|
|
33
|
+
if (event.request?.url) {
|
|
34
|
+
event.request.url = scrubTelemetryUrl(event.request.url);
|
|
35
|
+
}
|
|
36
|
+
if (event.request?.headers) {
|
|
37
|
+
for (const key of ["Referer", "referer"]) {
|
|
38
|
+
const value = event.request.headers[key];
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
event.request.headers[key] = scrubTelemetryUrl(value);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (event.transaction) {
|
|
45
|
+
event.transaction = scrubTelemetryUrl(event.transaction);
|
|
46
|
+
}
|
|
47
|
+
for (const crumb of event.breadcrumbs ?? []) {
|
|
48
|
+
if (!crumb.data) continue;
|
|
49
|
+
if (crumb.category === "navigation") {
|
|
50
|
+
for (const key of ["to", "from"]) {
|
|
51
|
+
const value = crumb.data[key];
|
|
52
|
+
if (typeof value === "string") {
|
|
53
|
+
crumb.data[key] = scrubTelemetryUrl(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// fetch/xhr breadcrumbs (and others) can carry `data.url` independent
|
|
58
|
+
// of category — scrub it regardless (security review, PR #5639).
|
|
59
|
+
const url = crumb.data["url"];
|
|
60
|
+
if (typeof url === "string") {
|
|
61
|
+
crumb.data["url"] = scrubTelemetryUrl(url);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const scrubSpanData = (data?: Record<string, unknown>): void => {
|
|
65
|
+
if (!data) return;
|
|
66
|
+
for (const key of [
|
|
67
|
+
"url.full",
|
|
68
|
+
"http.url",
|
|
69
|
+
"http.request.header.referer",
|
|
70
|
+
]) {
|
|
71
|
+
const value = data[key];
|
|
72
|
+
if (typeof value === "string") {
|
|
73
|
+
data[key] = scrubTelemetryUrl(value);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
scrubSpanData(event.contexts?.trace?.data);
|
|
78
|
+
for (const span of event.spans ?? []) {
|
|
79
|
+
scrubSpanData(span.data);
|
|
80
|
+
}
|
|
81
|
+
return event;
|
|
82
|
+
}
|
|
83
|
+
|
|
15
84
|
Sentry.init({
|
|
16
85
|
dsn: process.env.SENTRY_DSN,
|
|
17
86
|
enabled: !!process.env.SENTRY_DSN,
|
|
18
87
|
|
|
19
88
|
tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
|
|
89
|
+
|
|
90
|
+
beforeSend: scrubSentryEvent,
|
|
91
|
+
beforeSendTransaction: scrubSentryEvent,
|
|
20
92
|
});
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* handlers to avoid copy-paste duplication.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { routeFor } from "@working-theory/templates/routes";
|
|
9
|
+
|
|
8
10
|
import { SITE_BASE_URL } from "../../lib/site-brand";
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -29,22 +31,15 @@ export function resolveBaseUrl(): string {
|
|
|
29
31
|
/**
|
|
30
32
|
* Maps a content-adapter page type + slug to a site-relative path.
|
|
31
33
|
* Drives both /llms.txt and /sitemap.xml URL generation.
|
|
34
|
+
*
|
|
35
|
+
* A lookup over the routes map (#5572 U2, spec § D4 row 1) — `routeFor` is
|
|
36
|
+
* byte-identical to the switch this replaced for its six `case` literals and
|
|
37
|
+
* the `` `/${slug}` `` default (proven by
|
|
38
|
+
* `packages/templates/src/__tests__/routes-map.test.ts`'s table test and
|
|
39
|
+
* `apps/web/__tests__/routes/routes-map-identity.test.ts`'s differential
|
|
40
|
+
* test over the live content tree). The signature is annotated explicitly so
|
|
41
|
+
* this stays the exact `(type: string, slug: string) => string` contract the
|
|
42
|
+
* three call sites (`sitemap.xml`, `llms.txt`, `docs-blog/llms-route.ts`)
|
|
43
|
+
* depend on, even though `routeFor`'s own `slug` parameter is optional.
|
|
32
44
|
*/
|
|
33
|
-
export
|
|
34
|
-
switch (type) {
|
|
35
|
-
case "HomePage":
|
|
36
|
-
return "/";
|
|
37
|
-
case "BlogPosting":
|
|
38
|
-
return `/blog/${slug}`;
|
|
39
|
-
case "Product":
|
|
40
|
-
return `/products/${slug}`;
|
|
41
|
-
case "Service":
|
|
42
|
-
return `/services/${slug}`;
|
|
43
|
-
case "AboutPage":
|
|
44
|
-
return "/about";
|
|
45
|
-
case "ContactPage":
|
|
46
|
-
return "/contact";
|
|
47
|
-
default:
|
|
48
|
-
return `/${slug}`;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
45
|
+
export const slugToPath: (type: string, slug: string) => string = routeFor;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# brand_assets/
|
|
2
|
+
|
|
3
|
+
This folder is where you put your project's real brand material. It ships
|
|
4
|
+
empty — nothing here is required to run `pnpm dev` — but populating it is
|
|
5
|
+
what lets Claude Code (and anyone else building this site) use your actual
|
|
6
|
+
brand instead of inventing placeholder colors and copy.
|
|
7
|
+
|
|
8
|
+
`apps/web/CLAUDE.md` reads from this folder before designing a page. If a
|
|
9
|
+
file below is present, it's used; if it's absent, generic defaults are used
|
|
10
|
+
instead.
|
|
11
|
+
|
|
12
|
+
## What goes here
|
|
13
|
+
|
|
14
|
+
| File / folder | Contents |
|
|
15
|
+
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `logo.svg` (or `.png`) | Your logo, ideally an SVG. Add light/dark variants if your mark needs them (e.g. `logo-dark.svg`). |
|
|
17
|
+
| `brand-guide.md` | The global theme — brand colors, type direction, tone of voice, do's and don'ts — used when choosing layout and components for a page. |
|
|
18
|
+
| `brand-brief.md` | Positioning, messaging, and the target citation phrases a page's content should work toward. |
|
|
19
|
+
| `favicon.ico` / `favicon-*.png` | Favicon assets for `apps/web/app/favicon.ico` and any additional sizes your deploy target wants. |
|
|
20
|
+
| `photos/` | Real photography — team, product, office — to use instead of stock or placeholder images. |
|
|
21
|
+
| `reference/` | Mockups, screenshots, or other visual references to match when building or reviewing a page's design. |
|
|
22
|
+
|
|
23
|
+
None of these are mandatory. Add what you have; the rest can stay
|
|
24
|
+
placeholder until you're ready.
|
|
@@ -1,29 +1,174 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: "AboutPage"
|
|
3
3
|
slug: "about"
|
|
4
|
-
title: "
|
|
5
|
-
description: "
|
|
4
|
+
title: "We want you to {ability they couldn't do before}"
|
|
5
|
+
description: "We want you to {ability they couldn't do before}"
|
|
6
6
|
sections:
|
|
7
7
|
[
|
|
8
8
|
{
|
|
9
|
-
"id": "
|
|
10
|
-
"type": "
|
|
11
|
-
"data":
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
"id": "manifesto",
|
|
10
|
+
"type": "content-block",
|
|
11
|
+
"data": {
|
|
12
|
+
"variant": "media-right",
|
|
13
|
+
"eyebrow": "Manifesto",
|
|
14
|
+
"headline": "We want you to {ability they couldn't do before}",
|
|
15
|
+
"body": "Hey, I’m {your name}, the founder of {your company}.\n\nWrite a few sentences introducing the problems you solve. You can even ask a rhetorical question to get people thinking about their own personal experiences with a problem they might have encountered.\n\nThis is your chance to tell the backstory of why your product exists and explain the gap your product fills. Don’t be afraid to take a stance and plant your flag.\n\nWe believe that {you should be able to X without Y}.\n\nWe’ll help you:\n\nSolve this problem\n\nSolve another problem\n\nSolve this other problem\n\nIf that resonates with you, you're in the right place.\n\n- (your name)",
|
|
16
|
+
"cta": {
|
|
17
|
+
"label": "Sign Up",
|
|
18
|
+
"href": "/sign-in"
|
|
15
19
|
},
|
|
20
|
+
"secondaryCta": {
|
|
21
|
+
"label": "More about us",
|
|
22
|
+
"href": "/about",
|
|
23
|
+
"variant": "outline"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
16
26
|
},
|
|
17
27
|
{
|
|
18
|
-
"id": "
|
|
19
|
-
"type": "
|
|
20
|
-
"data":
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
"id": "team",
|
|
29
|
+
"type": "team",
|
|
30
|
+
"data": {
|
|
31
|
+
"headline": "Our team",
|
|
32
|
+
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
33
|
+
"members": [
|
|
34
|
+
{
|
|
35
|
+
"name": "Anya Lind",
|
|
36
|
+
"role": "Head of Growth",
|
|
37
|
+
"bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "Narciso Gerlach",
|
|
41
|
+
"role": "Head of Sales",
|
|
42
|
+
"bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "Edythe Sanford",
|
|
46
|
+
"role": "Head of Content",
|
|
47
|
+
"bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "Angeline Watsica",
|
|
51
|
+
"role": "Head of Conversion",
|
|
52
|
+
"bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "Gerardo Ullrich",
|
|
56
|
+
"role": "Head of Marketing",
|
|
57
|
+
"bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "logo-cloud",
|
|
64
|
+
"type": "logoCloud",
|
|
65
|
+
"data": {
|
|
66
|
+
"headline": "Don’t just take our word for it",
|
|
67
|
+
"logos": [
|
|
68
|
+
{
|
|
69
|
+
"name": "Placeholder logo",
|
|
70
|
+
"src": "/logomark.svg"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "Placeholder logo",
|
|
74
|
+
"src": "/logomark.svg"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "Placeholder logo",
|
|
78
|
+
"src": "/logomark.svg"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "Placeholder logo",
|
|
82
|
+
"src": "/logomark.svg"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "Placeholder logo",
|
|
86
|
+
"src": "/logomark.svg"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "Placeholder logo",
|
|
90
|
+
"src": "/logomark.svg"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"layout": "inline",
|
|
94
|
+
"treatment": "monochrome"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"id": "testimonial",
|
|
99
|
+
"type": "testimonials",
|
|
100
|
+
"data": {
|
|
101
|
+
"variant": "featured",
|
|
102
|
+
"items": [
|
|
103
|
+
{
|
|
104
|
+
"quote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat.",
|
|
105
|
+
"author": "John Smith",
|
|
106
|
+
"role": "CEO, Google"
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "switch",
|
|
113
|
+
"type": "cta",
|
|
114
|
+
"data": {
|
|
115
|
+
"variant": "box",
|
|
116
|
+
"headline": "Switch to {your product} in {time amount} or less",
|
|
117
|
+
"description": "You shouldn't have to {experience a painful problem}. With {your product}, you can finally {achieve a value outcome or get a big improvement}.",
|
|
118
|
+
"chips": [
|
|
119
|
+
"No credit card required",
|
|
120
|
+
"Cancel any time",
|
|
121
|
+
"Live chat support"
|
|
122
|
+
],
|
|
123
|
+
"primaryCta": {
|
|
124
|
+
"label": "{Primary CTA}",
|
|
125
|
+
"href": "/contact"
|
|
126
|
+
},
|
|
127
|
+
"secondaryCta": {
|
|
128
|
+
"label": "{Secondary CTA}",
|
|
129
|
+
"href": "/pricing",
|
|
130
|
+
"variant": "outline"
|
|
24
131
|
},
|
|
132
|
+
"closingLine": "{Social Proof goes here}"
|
|
133
|
+
}
|
|
25
134
|
},
|
|
135
|
+
{
|
|
136
|
+
"id": "faq",
|
|
137
|
+
"type": "faq",
|
|
138
|
+
"data": {
|
|
139
|
+
"headline": "FAQs",
|
|
140
|
+
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
|
|
141
|
+
"supportLink": {
|
|
142
|
+
"label": "Contact",
|
|
143
|
+
"href": "/contact"
|
|
144
|
+
},
|
|
145
|
+
"presentation": "accordion",
|
|
146
|
+
"initialOpen": "first",
|
|
147
|
+
"items": [
|
|
148
|
+
{
|
|
149
|
+
"question": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa?",
|
|
150
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"question": "Dolorem consectetur quia maxime sunt ut sint. Fuga optio dolorem animi voluptatem laudantium error. Quis accusamus deleniti rer?",
|
|
154
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"question": "Totam nihil esse. Itaque optio temporibus adipisci. Rerum nisi aperiam aliquid doloremque aliquam?",
|
|
158
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"question": "Delectus minus officiis et. Perspiciatis illum nisi vitae. Sed consequuntur animi corrupti distinctio ipsam accusamus?",
|
|
162
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"question": "Aperiam perferendis voluptatem est sit enim sed eaque perspiciatis enim. Est explicabo ea explicabo et et dignissimos aliquid?",
|
|
166
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
26
171
|
]
|
|
27
172
|
---
|
|
28
173
|
|
|
29
|
-
{/* Rendered from frontmatter `sections[]`.
|
|
174
|
+
{/* Rendered from frontmatter `sections[]`. Placeholder copy, verbatim from the reference — replace the manifesto and the team before you launch. */}
|
|
@@ -2,27 +2,104 @@
|
|
|
2
2
|
type: "ContactPage"
|
|
3
3
|
slug: "contact"
|
|
4
4
|
title: "Contact {{COMPANY_NAME}}"
|
|
5
|
-
description: "
|
|
5
|
+
description: "Find out if {your product} is a good fit for you in just {time amount}."
|
|
6
6
|
sections:
|
|
7
7
|
[
|
|
8
8
|
{
|
|
9
9
|
"id": "hero",
|
|
10
10
|
"type": "hero",
|
|
11
|
-
"data":
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
11
|
+
"data": {
|
|
12
|
+
"variant": "split",
|
|
13
|
+
"eyebrow": "Book a Demo",
|
|
14
|
+
"headline": "Ready to {achieve a valuable outcome}?",
|
|
15
|
+
"subheadline": "Find out if {your product} is a good fit for you in just {time amount}.",
|
|
16
|
+
"checklist": [
|
|
17
|
+
"Use these bullet points to describe what to expect on the call",
|
|
18
|
+
"Alleviate any fears or hesitations visitors might have before scheduling",
|
|
19
|
+
"Frame the meeting around what they get out of it instead of what you get out of it"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
16
22
|
},
|
|
17
23
|
{
|
|
18
|
-
"id": "
|
|
19
|
-
"type": "
|
|
20
|
-
"data":
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
"id": "contact-form",
|
|
25
|
+
"type": "contact-form",
|
|
26
|
+
"data": {
|
|
27
|
+
"variant": "card",
|
|
28
|
+
"fields": [
|
|
29
|
+
{
|
|
30
|
+
"name": "name",
|
|
31
|
+
"label": "Name",
|
|
32
|
+
"type": "text",
|
|
33
|
+
"required": true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "email",
|
|
37
|
+
"label": "Email",
|
|
38
|
+
"type": "email",
|
|
39
|
+
"required": true
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "message",
|
|
43
|
+
"label": "Message",
|
|
44
|
+
"type": "textarea",
|
|
45
|
+
"required": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"consentText": "I accept the Terms",
|
|
49
|
+
"successMessage": "Thank you! Your submission has been received!",
|
|
50
|
+
"action": "/v1/leads/submit"
|
|
51
|
+
}
|
|
24
52
|
},
|
|
53
|
+
{
|
|
54
|
+
"id": "logo-cloud",
|
|
55
|
+
"type": "logoCloud",
|
|
56
|
+
"data": {
|
|
57
|
+
"headline": "Don’t just take our word for it",
|
|
58
|
+
"logos": [
|
|
59
|
+
{
|
|
60
|
+
"name": "Placeholder logo",
|
|
61
|
+
"src": "/logomark.svg"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "Placeholder logo",
|
|
65
|
+
"src": "/logomark.svg"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "Placeholder logo",
|
|
69
|
+
"src": "/logomark.svg"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "Placeholder logo",
|
|
73
|
+
"src": "/logomark.svg"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "Placeholder logo",
|
|
77
|
+
"src": "/logomark.svg"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "Placeholder logo",
|
|
81
|
+
"src": "/logomark.svg"
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"layout": "inline",
|
|
85
|
+
"treatment": "monochrome"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "testimonial",
|
|
90
|
+
"type": "testimonials",
|
|
91
|
+
"data": {
|
|
92
|
+
"variant": "featured",
|
|
93
|
+
"items": [
|
|
94
|
+
{
|
|
95
|
+
"quote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat.",
|
|
96
|
+
"author": "John Smith",
|
|
97
|
+
"role": "CEO, Google"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
25
102
|
]
|
|
26
103
|
---
|
|
27
104
|
|
|
28
|
-
{/* Rendered from frontmatter `sections[]`.
|
|
105
|
+
{/* Rendered from frontmatter `sections[]`. The form posts to the site's own API (`/v1/leads/submit`) and confirms inline. Placeholder copy — replace before you launch. */}
|
|
@@ -1,38 +1,78 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: "FAQPage"
|
|
3
3
|
slug: "faq"
|
|
4
|
-
title: "{{COMPANY_NAME}} —
|
|
5
|
-
description: "
|
|
4
|
+
title: "{{COMPANY_NAME}} — FAQs"
|
|
5
|
+
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
6
6
|
sections:
|
|
7
7
|
[
|
|
8
8
|
{
|
|
9
|
-
"id": "
|
|
9
|
+
"id": "hero",
|
|
10
10
|
"type": "hero",
|
|
11
|
-
"data":
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
11
|
+
"data": {
|
|
12
|
+
"headline": "FAQs",
|
|
13
|
+
"subheadline": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
|
|
14
|
+
}
|
|
16
15
|
},
|
|
17
16
|
{
|
|
18
17
|
"id": "faq",
|
|
19
18
|
"type": "faq",
|
|
20
|
-
"data":
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"question": "Replace this with a real question you get asked.",
|
|
26
|
-
"answer": "Answer it directly, in the first sentence. An FAQ answer that opens with context and buries the answer in paragraph three does not get quoted.",
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"question": "What makes a good FAQ entry?",
|
|
30
|
-
"answer": "A question phrased the way someone would actually ask it, and an answer that stands alone without the rest of the page. This page emits FAQPage JSON-LD, so each pair is machine-readable on its own.",
|
|
31
|
-
},
|
|
32
|
-
],
|
|
19
|
+
"data": {
|
|
20
|
+
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
|
|
21
|
+
"supportLink": {
|
|
22
|
+
"label": "Contact",
|
|
23
|
+
"href": "/contact"
|
|
33
24
|
},
|
|
25
|
+
"presentation": "accordion",
|
|
26
|
+
"initialOpen": "first",
|
|
27
|
+
"items": [
|
|
28
|
+
{
|
|
29
|
+
"question": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa?",
|
|
30
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"question": "Dolorem consectetur quia maxime sunt ut sint. Fuga optio dolorem animi voluptatem laudantium error. Quis accusamus deleniti rer?",
|
|
34
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"question": "Totam nihil esse. Itaque optio temporibus adipisci. Rerum nisi aperiam aliquid doloremque aliquam?",
|
|
38
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"question": "Delectus minus officiis et. Perspiciatis illum nisi vitae. Sed consequuntur animi corrupti distinctio ipsam accusamus?",
|
|
42
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"question": "Aperiam perferendis voluptatem est sit enim sed eaque perspiciatis enim. Est explicabo ea explicabo et et dignissimos aliquid?",
|
|
46
|
+
"answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
34
50
|
},
|
|
51
|
+
{
|
|
52
|
+
"id": "switch",
|
|
53
|
+
"type": "cta",
|
|
54
|
+
"data": {
|
|
55
|
+
"variant": "box",
|
|
56
|
+
"headline": "Switch to {your product} in {time amount} or less",
|
|
57
|
+
"description": "You shouldn't have to {experience a painful problem}. With {your product}, you can finally {achieve a value outcome or get a big improvement}.",
|
|
58
|
+
"chips": [
|
|
59
|
+
"No credit card required",
|
|
60
|
+
"Cancel any time",
|
|
61
|
+
"Live chat support"
|
|
62
|
+
],
|
|
63
|
+
"primaryCta": {
|
|
64
|
+
"label": "{Primary CTA}",
|
|
65
|
+
"href": "/contact"
|
|
66
|
+
},
|
|
67
|
+
"secondaryCta": {
|
|
68
|
+
"label": "{Secondary CTA}",
|
|
69
|
+
"href": "/pricing",
|
|
70
|
+
"variant": "outline"
|
|
71
|
+
},
|
|
72
|
+
"closingLine": "{Social Proof goes here}"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
35
75
|
]
|
|
36
76
|
---
|
|
37
77
|
|
|
38
|
-
{/* Rendered from frontmatter `sections[]`. Each question/answer pair is emitted as schema.org FAQPage structured data — keep answers self-contained. */}
|
|
78
|
+
{/* Rendered from frontmatter `sections[]`. Each question/answer pair is emitted as schema.org FAQPage structured data — keep answers self-contained. Placeholder copy — replace before you launch. */}
|