@contractspec/bundle.marketing 1.12.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.
Files changed (216) hide show
  1. package/.turbo/turbo-build$colon$types.log +1 -0
  2. package/.turbo/turbo-build.log +175 -0
  3. package/.turbo/turbo-lint.log +3 -0
  4. package/AGENTS.md +36 -0
  5. package/CHANGELOG.md +416 -0
  6. package/README.md +57 -0
  7. package/dist/components/marketing/ChangelogPage.d.ts +21 -0
  8. package/dist/components/marketing/ChangelogPage.d.ts.map +1 -0
  9. package/dist/components/marketing/ChangelogPage.js +65 -0
  10. package/dist/components/marketing/ChangelogPage.js.map +1 -0
  11. package/dist/components/marketing/CofounderPage.d.ts +7 -0
  12. package/dist/components/marketing/CofounderPage.d.ts.map +1 -0
  13. package/dist/components/marketing/CofounderPage.js +468 -0
  14. package/dist/components/marketing/CofounderPage.js.map +1 -0
  15. package/dist/components/marketing/ContactClient.d.ts +7 -0
  16. package/dist/components/marketing/ContactClient.d.ts.map +1 -0
  17. package/dist/components/marketing/ContactClient.js +158 -0
  18. package/dist/components/marketing/ContactClient.js.map +1 -0
  19. package/dist/components/marketing/ContributePage.d.ts +9 -0
  20. package/dist/components/marketing/ContributePage.d.ts.map +1 -0
  21. package/dist/components/marketing/ContributePage.js +362 -0
  22. package/dist/components/marketing/ContributePage.js.map +1 -0
  23. package/dist/components/marketing/DesignPartnerPage.d.ts +9 -0
  24. package/dist/components/marketing/DesignPartnerPage.d.ts.map +1 -0
  25. package/dist/components/marketing/DesignPartnerPage.js +215 -0
  26. package/dist/components/marketing/DesignPartnerPage.js.map +1 -0
  27. package/dist/components/marketing/LandingPage.d.ts +7 -0
  28. package/dist/components/marketing/LandingPage.d.ts.map +1 -0
  29. package/dist/components/marketing/LandingPage.js +38 -0
  30. package/dist/components/marketing/LandingPage.js.map +1 -0
  31. package/dist/components/marketing/PricingClient.d.ts +7 -0
  32. package/dist/components/marketing/PricingClient.d.ts.map +1 -0
  33. package/dist/components/marketing/PricingClient.js +521 -0
  34. package/dist/components/marketing/PricingClient.js.map +1 -0
  35. package/dist/components/marketing/ProductClientPage.d.ts +7 -0
  36. package/dist/components/marketing/ProductClientPage.d.ts.map +1 -0
  37. package/dist/components/marketing/ProductClientPage.js +460 -0
  38. package/dist/components/marketing/ProductClientPage.js.map +1 -0
  39. package/dist/components/marketing/index.d.ts +11 -0
  40. package/dist/components/marketing/index.js +12 -0
  41. package/dist/components/marketing/pricing-thinking-modal.d.ts +16 -0
  42. package/dist/components/marketing/pricing-thinking-modal.d.ts.map +1 -0
  43. package/dist/components/marketing/pricing-thinking-modal.js +202 -0
  44. package/dist/components/marketing/pricing-thinking-modal.js.map +1 -0
  45. package/dist/components/marketing/sections/AudienceSection.d.ts +7 -0
  46. package/dist/components/marketing/sections/AudienceSection.d.ts.map +1 -0
  47. package/dist/components/marketing/sections/AudienceSection.js +68 -0
  48. package/dist/components/marketing/sections/AudienceSection.js.map +1 -0
  49. package/dist/components/marketing/sections/CorePositioningSection.d.ts +7 -0
  50. package/dist/components/marketing/sections/CorePositioningSection.d.ts.map +1 -0
  51. package/dist/components/marketing/sections/CorePositioningSection.js +59 -0
  52. package/dist/components/marketing/sections/CorePositioningSection.js.map +1 -0
  53. package/dist/components/marketing/sections/CtaSection.d.ts +7 -0
  54. package/dist/components/marketing/sections/CtaSection.d.ts.map +1 -0
  55. package/dist/components/marketing/sections/CtaSection.js +54 -0
  56. package/dist/components/marketing/sections/CtaSection.js.map +1 -0
  57. package/dist/components/marketing/sections/DevelopersSection.d.ts +7 -0
  58. package/dist/components/marketing/sections/DevelopersSection.d.ts.map +1 -0
  59. package/dist/components/marketing/sections/DevelopersSection.js +45 -0
  60. package/dist/components/marketing/sections/DevelopersSection.js.map +1 -0
  61. package/dist/components/marketing/sections/FearsSection.d.ts +7 -0
  62. package/dist/components/marketing/sections/FearsSection.d.ts.map +1 -0
  63. package/dist/components/marketing/sections/FearsSection.js +48 -0
  64. package/dist/components/marketing/sections/FearsSection.js.map +1 -0
  65. package/dist/components/marketing/sections/HeroMarketingSection.d.ts +7 -0
  66. package/dist/components/marketing/sections/HeroMarketingSection.d.ts.map +1 -0
  67. package/dist/components/marketing/sections/HeroMarketingSection.js +77 -0
  68. package/dist/components/marketing/sections/HeroMarketingSection.js.map +1 -0
  69. package/dist/components/marketing/sections/IconGridSection.d.ts +45 -0
  70. package/dist/components/marketing/sections/IconGridSection.d.ts.map +1 -0
  71. package/dist/components/marketing/sections/IconGridSection.js +44 -0
  72. package/dist/components/marketing/sections/IconGridSection.js.map +1 -0
  73. package/dist/components/marketing/sections/OutputsSection.d.ts +7 -0
  74. package/dist/components/marketing/sections/OutputsSection.d.ts.map +1 -0
  75. package/dist/components/marketing/sections/OutputsSection.js +59 -0
  76. package/dist/components/marketing/sections/OutputsSection.js.map +1 -0
  77. package/dist/components/marketing/sections/ProblemSection.d.ts +7 -0
  78. package/dist/components/marketing/sections/ProblemSection.d.ts.map +1 -0
  79. package/dist/components/marketing/sections/ProblemSection.js +46 -0
  80. package/dist/components/marketing/sections/ProblemSection.js.map +1 -0
  81. package/dist/components/marketing/sections/SolutionSection.d.ts +7 -0
  82. package/dist/components/marketing/sections/SolutionSection.d.ts.map +1 -0
  83. package/dist/components/marketing/sections/SolutionSection.js +46 -0
  84. package/dist/components/marketing/sections/SolutionSection.js.map +1 -0
  85. package/dist/components/marketing/sections/StepsSection.d.ts +7 -0
  86. package/dist/components/marketing/sections/StepsSection.d.ts.map +1 -0
  87. package/dist/components/marketing/sections/StepsSection.js +52 -0
  88. package/dist/components/marketing/sections/StepsSection.js.map +1 -0
  89. package/dist/components/marketing/waitlist-section.d.ts +15 -0
  90. package/dist/components/marketing/waitlist-section.d.ts.map +1 -0
  91. package/dist/components/marketing/waitlist-section.js +578 -0
  92. package/dist/components/marketing/waitlist-section.js.map +1 -0
  93. package/dist/components/templates/TemplatesClientPage.d.ts +7 -0
  94. package/dist/components/templates/TemplatesClientPage.d.ts.map +1 -0
  95. package/dist/components/templates/TemplatesClientPage.js +625 -0
  96. package/dist/components/templates/TemplatesClientPage.js.map +1 -0
  97. package/dist/components/templates/TemplatesPage.d.ts +7 -0
  98. package/dist/components/templates/TemplatesPage.d.ts.map +1 -0
  99. package/dist/components/templates/TemplatesPage.js +125 -0
  100. package/dist/components/templates/TemplatesPage.js.map +1 -0
  101. package/dist/components/templates/TemplatesPreviewModal.d.ts +15 -0
  102. package/dist/components/templates/TemplatesPreviewModal.d.ts.map +1 -0
  103. package/dist/components/templates/TemplatesPreviewModal.js +137 -0
  104. package/dist/components/templates/TemplatesPreviewModal.js.map +1 -0
  105. package/dist/components/templates/index.d.ts +4 -0
  106. package/dist/components/templates/index.js +5 -0
  107. package/dist/index.d.ts +29 -0
  108. package/dist/index.js +28 -0
  109. package/dist/libs/email/client.d.ts +15 -0
  110. package/dist/libs/email/client.d.ts.map +1 -0
  111. package/dist/libs/email/client.js +113 -0
  112. package/dist/libs/email/client.js.map +1 -0
  113. package/dist/libs/email/contact.d.ts +7 -0
  114. package/dist/libs/email/contact.d.ts.map +1 -0
  115. package/dist/libs/email/contact.js +71 -0
  116. package/dist/libs/email/contact.js.map +1 -0
  117. package/dist/libs/email/newsletter.d.ts +7 -0
  118. package/dist/libs/email/newsletter.d.ts.map +1 -0
  119. package/dist/libs/email/newsletter.js +95 -0
  120. package/dist/libs/email/newsletter.js.map +1 -0
  121. package/dist/libs/email/types.d.ts +53 -0
  122. package/dist/libs/email/types.d.ts.map +1 -0
  123. package/dist/libs/email/types.js +1 -0
  124. package/dist/libs/email/utils.d.ts +6 -0
  125. package/dist/libs/email/utils.d.ts.map +1 -0
  126. package/dist/libs/email/utils.js +7 -0
  127. package/dist/libs/email/utils.js.map +1 -0
  128. package/dist/libs/email/waitlist-application.d.ts +7 -0
  129. package/dist/libs/email/waitlist-application.d.ts.map +1 -0
  130. package/dist/libs/email/waitlist-application.js +170 -0
  131. package/dist/libs/email/waitlist-application.js.map +1 -0
  132. package/dist/libs/email/waitlist.d.ts +7 -0
  133. package/dist/libs/email/waitlist.d.ts.map +1 -0
  134. package/dist/libs/email/waitlist.js +105 -0
  135. package/dist/libs/email/waitlist.js.map +1 -0
  136. package/dist/libs/pricing-examples.d.ts +22 -0
  137. package/dist/libs/pricing-examples.d.ts.map +1 -0
  138. package/dist/libs/pricing-examples.js +21 -0
  139. package/dist/libs/pricing-examples.js.map +1 -0
  140. package/dist/registry/engine.d.ts +17 -0
  141. package/dist/registry/engine.d.ts.map +1 -0
  142. package/dist/registry/engine.js +24 -0
  143. package/dist/registry/engine.js.map +1 -0
  144. package/dist/registry/factory.d.ts +64 -0
  145. package/dist/registry/factory.d.ts.map +1 -0
  146. package/dist/registry/factory.js +61 -0
  147. package/dist/registry/factory.js.map +1 -0
  148. package/dist/registry/index.d.ts +8 -0
  149. package/dist/registry/index.js +8 -0
  150. package/dist/registry/registry-docs.d.ts +15 -0
  151. package/dist/registry/registry-docs.d.ts.map +1 -0
  152. package/dist/registry/registry-docs.js +305 -0
  153. package/dist/registry/registry-docs.js.map +1 -0
  154. package/dist/registry/registry-landing.d.ts +19 -0
  155. package/dist/registry/registry-landing.d.ts.map +1 -0
  156. package/dist/registry/registry-landing.js +95 -0
  157. package/dist/registry/registry-landing.js.map +1 -0
  158. package/dist/registry/registry.d.ts +30 -0
  159. package/dist/registry/registry.d.ts.map +1 -0
  160. package/dist/registry/registry.js +61 -0
  161. package/dist/registry/registry.js.map +1 -0
  162. package/dist/registry/types.d.ts +19 -0
  163. package/dist/registry/types.d.ts.map +1 -0
  164. package/dist/registry/types.js +0 -0
  165. package/dist/registry/utils.d.ts +31 -0
  166. package/dist/registry/utils.d.ts.map +1 -0
  167. package/dist/registry/utils.js +54 -0
  168. package/dist/registry/utils.js.map +1 -0
  169. package/package.json +151 -0
  170. package/src/components/marketing/ChangelogPage.tsx +110 -0
  171. package/src/components/marketing/CofounderPage.tsx +409 -0
  172. package/src/components/marketing/ContactClient.tsx +174 -0
  173. package/src/components/marketing/ContributePage.tsx +319 -0
  174. package/src/components/marketing/DesignPartnerPage.tsx +181 -0
  175. package/src/components/marketing/LandingPage.tsx +30 -0
  176. package/src/components/marketing/PricingClient.tsx +446 -0
  177. package/src/components/marketing/ProductClientPage.tsx +391 -0
  178. package/src/components/marketing/index.ts +10 -0
  179. package/src/components/marketing/pricing-thinking-modal.tsx +224 -0
  180. package/src/components/marketing/sections/AudienceSection.tsx +66 -0
  181. package/src/components/marketing/sections/CorePositioningSection.tsx +44 -0
  182. package/src/components/marketing/sections/CtaSection.tsx +57 -0
  183. package/src/components/marketing/sections/DevelopersSection.tsx +38 -0
  184. package/src/components/marketing/sections/FearsSection.tsx +45 -0
  185. package/src/components/marketing/sections/HeroMarketingSection.tsx +73 -0
  186. package/src/components/marketing/sections/IconGridSection.tsx +91 -0
  187. package/src/components/marketing/sections/OutputsSection.tsx +59 -0
  188. package/src/components/marketing/sections/ProblemSection.tsx +47 -0
  189. package/src/components/marketing/sections/SolutionSection.tsx +47 -0
  190. package/src/components/marketing/sections/StepsSection.tsx +55 -0
  191. package/src/components/marketing/waitlist-section.tsx +606 -0
  192. package/src/components/templates/TemplatesClientPage.tsx +711 -0
  193. package/src/components/templates/TemplatesPage.tsx +129 -0
  194. package/src/components/templates/TemplatesPreviewModal.tsx +260 -0
  195. package/src/components/templates/index.ts +3 -0
  196. package/src/index.ts +15 -0
  197. package/src/libs/email/client.test.ts +107 -0
  198. package/src/libs/email/client.ts +146 -0
  199. package/src/libs/email/contact.ts +80 -0
  200. package/src/libs/email/newsletter.ts +108 -0
  201. package/src/libs/email/types.ts +59 -0
  202. package/src/libs/email/utils.ts +8 -0
  203. package/src/libs/email/waitlist-application.ts +192 -0
  204. package/src/libs/email/waitlist.ts +118 -0
  205. package/src/libs/pricing-examples.ts +19 -0
  206. package/src/registry/engine.ts +38 -0
  207. package/src/registry/factory.ts +110 -0
  208. package/src/registry/index.ts +7 -0
  209. package/src/registry/registry-docs.ts +843 -0
  210. package/src/registry/registry-landing.ts +118 -0
  211. package/src/registry/registry.ts +85 -0
  212. package/src/registry/types.ts +17 -0
  213. package/src/registry/utils.ts +99 -0
  214. package/tsconfig.json +13 -0
  215. package/tsconfig.tsbuildinfo +1 -0
  216. package/tsdown.config.js +10 -0
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { MarketingSection, ButtonLink } from '@contractspec/lib.design-system';
3
+ import { VStack } from '@contractspec/lib.ui-kit-web/ui/stack';
4
+ import { H2, Lead, Small } from '@contractspec/lib.ui-kit-web/ui/typography';
5
+ import { ChevronRight } from 'lucide-react';
6
+
7
+ export function CorePositioningSection() {
8
+ return (
9
+ <MarketingSection
10
+ tone="gradient"
11
+ padding="comfortable"
12
+ align="center"
13
+ maxWidth="lg"
14
+ >
15
+ <VStack gap="md" align="center">
16
+ <H2 className="text-center text-3xl font-bold md:text-4xl">
17
+ You keep your app.
18
+ <br />
19
+ We stabilize it, one module at a time.
20
+ </H2>
21
+ <Lead className="text-center">
22
+ You own the code. It&apos;s standard tech.
23
+ <br />
24
+ <Small className="font-semibold text-violet-400">
25
+ We&apos;re the compiler, not the prison.
26
+ </Small>
27
+ </Lead>
28
+ <VStack
29
+ as="div"
30
+ gap="sm"
31
+ align="center"
32
+ className="pt-2 sm:flex sm:flex-row sm:flex-wrap sm:items-center sm:justify-center"
33
+ >
34
+ <ButtonLink href="/pricing#waitlist">
35
+ Join waitlist <ChevronRight size={16} />
36
+ </ButtonLink>
37
+ <ButtonLink variant="ghost" href="/contact">
38
+ Book a call
39
+ </ButtonLink>
40
+ </VStack>
41
+ </VStack>
42
+ </MarketingSection>
43
+ );
44
+ }
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ import { MarketingSection, ButtonLink } from '@contractspec/lib.design-system';
3
+ import {
4
+ analyticsEventNames,
5
+ captureAnalyticsEvent,
6
+ } from '@contractspec/bundle.library/libs/posthog/client';
7
+ import { VStack } from '@contractspec/lib.ui-kit-web/ui/stack';
8
+ import { H2, Lead } from '@contractspec/lib.ui-kit-web/ui/typography';
9
+
10
+ export function CtaSection() {
11
+ return (
12
+ <MarketingSection
13
+ tone="gradient"
14
+ padding="comfortable"
15
+ align="center"
16
+ maxWidth="lg"
17
+ >
18
+ <VStack gap="md" align="center" className="text-center">
19
+ <H2 className="text-4xl font-bold md:text-5xl">
20
+ Ready to stabilize your codebase?
21
+ </H2>
22
+ <Lead className="text-muted-foreground text-lg">
23
+ Start with one module. See the difference. Expand at your own pace.
24
+ </Lead>
25
+ <VStack
26
+ as="div"
27
+ gap="sm"
28
+ align="center"
29
+ className="pt-2 sm:flex sm:flex-row sm:flex-wrap sm:items-center sm:justify-center"
30
+ >
31
+ <ButtonLink
32
+ href="/pricing#waitlist"
33
+ onClick={() =>
34
+ captureAnalyticsEvent(analyticsEventNames.CTA_STUDIO_CLICK, {
35
+ surface: 'cta-section',
36
+ })
37
+ }
38
+ >
39
+ Join waitlist
40
+ </ButtonLink>
41
+ <ButtonLink
42
+ variant="ghost"
43
+ href="/contact"
44
+ onClick={() =>
45
+ captureAnalyticsEvent(analyticsEventNames.CTA_STUDIO_CLICK, {
46
+ surface: 'cta-section',
47
+ variant: 'contact',
48
+ })
49
+ }
50
+ >
51
+ Book a call
52
+ </ButtonLink>
53
+ </VStack>
54
+ </VStack>
55
+ </MarketingSection>
56
+ );
57
+ }
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+ import {
3
+ ButtonLink,
4
+ MarketingComparisonSection,
5
+ } from '@contractspec/lib.design-system';
6
+
7
+ const standardTech = [
8
+ 'TypeScript & Zod — schemas you already know',
9
+ 'Prisma — standard database access',
10
+ 'GraphQL or REST — your choice',
11
+ 'React or any UI framework',
12
+ 'Bun, Node, Deno — all supported',
13
+ ];
14
+
15
+ const noMagic = [
16
+ 'Generated code is readable & modifiable',
17
+ 'No proprietary runtime dependencies',
18
+ 'Eject anytime, keep everything',
19
+ 'Works with your existing CI/CD',
20
+ 'Open spec format',
21
+ ];
22
+
23
+ export function DevelopersSection() {
24
+ return (
25
+ <MarketingComparisonSection
26
+ tone="muted"
27
+ title="Built for developers"
28
+ padding="comfortable"
29
+ left={{ title: 'Standard Tech Stack', items: standardTech }}
30
+ right={{ title: 'No Magic, No Lock-in', items: noMagic }}
31
+ subtitle={
32
+ <ButtonLink href="/docs">
33
+ Read the docs <span aria-hidden>→</span>
34
+ </ButtonLink>
35
+ }
36
+ />
37
+ );
38
+ }
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import { CheckCircle, Code, Unlock, Zap } from 'lucide-react';
3
+ import { IconGridSection } from './IconGridSection';
4
+
5
+ const fears = [
6
+ {
7
+ title: '"I already have an app"',
8
+ body: "ContractSpec works with existing codebases. You don't start over — you stabilize incrementally, one module at a time. Start with one API endpoint, one data model, one contract.",
9
+ icon: CheckCircle,
10
+ },
11
+ {
12
+ title: '"Vendor lock-in / losing ownership"',
13
+ body: "You own the generated code. It's standard TypeScript, standard SQL, standard GraphQL. ContractSpec is a compiler — like TypeScript itself. You can eject anytime.",
14
+ icon: Unlock,
15
+ },
16
+ {
17
+ title: '"Adoption cost / learning curve"',
18
+ body: 'Specs are just TypeScript. If you can write z.object({ name: z.string() }), you can write a ContractSpec. No new language, no magic DSL, no YAML.',
19
+ icon: Code,
20
+ },
21
+ {
22
+ title: '"Forced migrations / magical runtime"',
23
+ body: "ContractSpec generates plain code you can read, debug, and modify. There's no proprietary runtime. Migrations are explicit, reversible, and in your control.",
24
+ icon: Zap,
25
+ },
26
+ ];
27
+
28
+ export function FearsSection() {
29
+ return (
30
+ <IconGridSection
31
+ tone="muted"
32
+ columns={2}
33
+ eyebrow="We Get It"
34
+ title="Your fears, addressed"
35
+ subtitle="We know what you're thinking. Here's why those concerns don't apply to ContractSpec."
36
+ iconRole="support"
37
+ items={fears.map((item) => ({
38
+ icon: item.icon,
39
+ title: item.title,
40
+ description: item.body,
41
+ iconClassName: 'text-violet-400',
42
+ }))}
43
+ />
44
+ );
45
+ }
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import { ButtonLink, MarketingSection } from '@contractspec/lib.design-system';
4
+ import {
5
+ analyticsEventNames,
6
+ captureAnalyticsEvent,
7
+ } from '@contractspec/bundle.library/libs/posthog/client';
8
+ import { Box, HStack, VStack } from '@contractspec/lib.ui-kit-web/ui/stack';
9
+ import { H1, Lead, Small } from '@contractspec/lib.ui-kit-web/ui/typography';
10
+ import { ChevronRight } from 'lucide-react';
11
+
12
+ const heroChips = ['Multi-Surface Sync', 'No Lock-in', 'Standard Tech'];
13
+
14
+ export function HeroMarketingSection() {
15
+ return (
16
+ <MarketingSection tone="gradient" padding="spacious" align="center">
17
+ <VStack gap="lg" align="center" className="text-center">
18
+ <Box
19
+ as="div"
20
+ role="presentation"
21
+ className="bg-muted text-muted-foreground inline-flex items-center rounded-full px-3 py-1 text-xs font-medium tracking-wider uppercase"
22
+ >
23
+ Open Source Core
24
+ </Box>
25
+ <H1 className="text-4xl leading-tight font-bold text-balance md:text-5xl">
26
+ Stabilize your AI-generated code
27
+ </H1>
28
+ <Lead className="text-muted-foreground text-lg text-balance md:text-xl">
29
+ ContractSpec is the compiler that keeps AI-written software coherent,
30
+ safe, and regenerable. You keep your app. You own the code. One module
31
+ at a time.
32
+ </Lead>
33
+
34
+ <HStack gap="md" justify="center" wrap="wrap">
35
+ <ButtonLink
36
+ href="/install"
37
+ onClick={() =>
38
+ captureAnalyticsEvent(analyticsEventNames.CTA_INSTALL_CLICK, {
39
+ surface: 'hero',
40
+ })
41
+ }
42
+ >
43
+ Install OSS <ChevronRight size={16} />
44
+ </ButtonLink>
45
+ <ButtonLink
46
+ variant="ghost"
47
+ href="/contact#waitlist"
48
+ onClick={() =>
49
+ captureAnalyticsEvent(analyticsEventNames.CTA_STUDIO_CLICK, {
50
+ surface: 'hero',
51
+ })
52
+ }
53
+ >
54
+ Join Studio Waitlist
55
+ </ButtonLink>
56
+ </HStack>
57
+
58
+ <HStack gap="sm" justify="center" wrap="wrap" className="pt-2">
59
+ {heroChips.map((chip) => (
60
+ <Box
61
+ key={chip}
62
+ as="div"
63
+ role="presentation"
64
+ className="border-border text-foreground inline-flex items-center rounded-full border px-3 py-1 text-sm"
65
+ >
66
+ <Small className="font-medium">{chip}</Small>
67
+ </Box>
68
+ ))}
69
+ </HStack>
70
+ </VStack>
71
+ </MarketingSection>
72
+ );
73
+ }
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import {
4
+ MarketingCardsSection,
5
+ MarketingIconCard,
6
+ type MarketingCardTone,
7
+ type MarketingSectionPadding,
8
+ type MarketingSectionTone,
9
+ } from '@contractspec/lib.design-system';
10
+ import { Muted } from '@contractspec/lib.ui-kit-web/ui/typography';
11
+
12
+ type IconComponent = React.ComponentType<{ className?: string; size?: number }>;
13
+
14
+ export interface IconGridItem {
15
+ icon: IconComponent;
16
+ title: string;
17
+ description: string;
18
+ iconClassName?: string;
19
+ tone?: MarketingCardTone;
20
+ }
21
+
22
+ interface IconGridSectionProps {
23
+ eyebrow?: string;
24
+ title: string;
25
+ subtitle?: string;
26
+ items: IconGridItem[];
27
+ tone?: MarketingSectionTone;
28
+ padding?: MarketingSectionPadding;
29
+ columns?: 2 | 3 | 4;
30
+ iconRole?: IconGridSectionRole;
31
+ }
32
+
33
+ const itemVariants = cva('', {
34
+ variants: {
35
+ iconRole: {
36
+ iconFirst: '',
37
+ listing: 'items-start',
38
+ support: 'items-start',
39
+ },
40
+ },
41
+ defaultVariants: { iconRole: 'iconFirst' },
42
+ });
43
+
44
+ export type IconGridSectionRole = VariantProps<typeof itemVariants>['iconRole'];
45
+
46
+ export function IconGridSection({
47
+ eyebrow,
48
+ title,
49
+ subtitle,
50
+ items,
51
+ tone = 'default',
52
+ padding,
53
+ columns = 3,
54
+ iconRole = 'iconFirst',
55
+ }: IconGridSectionProps) {
56
+ return (
57
+ <MarketingCardsSection
58
+ tone={tone}
59
+ padding={padding}
60
+ eyebrow={
61
+ eyebrow ? (
62
+ <Muted className="text-xs font-semibold tracking-[0.2em] uppercase">
63
+ {eyebrow}
64
+ </Muted>
65
+ ) : null
66
+ }
67
+ title={title}
68
+ subtitle={subtitle ? <Muted className="text-lg">{subtitle}</Muted> : null}
69
+ columns={columns}
70
+ >
71
+ {items.map((card) => (
72
+ <MarketingIconCard
73
+ key={card.title}
74
+ icon={card.icon}
75
+ title={card.title}
76
+ description={card.description}
77
+ tone={card.tone}
78
+ iconClassName={card.iconClassName}
79
+ variant={
80
+ iconRole === 'listing'
81
+ ? 'listing'
82
+ : iconRole === 'support'
83
+ ? 'support'
84
+ : 'iconFirst'
85
+ }
86
+ className={itemVariants({ iconRole })}
87
+ />
88
+ ))}
89
+ </MarketingCardsSection>
90
+ );
91
+ }
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+ import { IconGridSection } from './IconGridSection';
3
+
4
+ const outputs = [
5
+ {
6
+ title: 'REST API',
7
+ description:
8
+ 'Type-safe endpoints with validation. Standard Express/Hono/Elysia handlers.',
9
+ icon: '🔌',
10
+ },
11
+ {
12
+ title: 'GraphQL Schema',
13
+ description:
14
+ 'Automatically generated resolvers. Standard Pothos/Apollo output.',
15
+ icon: '📊',
16
+ },
17
+ {
18
+ title: 'Database Schema',
19
+ description: 'Prisma migrations and types. Standard SQL underneath.',
20
+ icon: '🗄️',
21
+ },
22
+ {
23
+ title: 'MCP Tools',
24
+ description:
25
+ 'AI agent tool definitions. Works with Claude, GPT, and any MCP client.',
26
+ icon: '🤖',
27
+ },
28
+ {
29
+ title: 'Client SDKs',
30
+ description: 'Type-safe API clients. Standard fetch/axios underneath.',
31
+ icon: '📦',
32
+ },
33
+ {
34
+ title: 'UI Components',
35
+ description: 'React forms and views from specs. Standard JSX output.',
36
+ icon: '🎨',
37
+ },
38
+ ];
39
+
40
+ export function OutputsSection() {
41
+ return (
42
+ <IconGridSection
43
+ tone="muted"
44
+ columns={3}
45
+ title="What ContractSpec generates"
46
+ subtitle="One contract, multiple outputs. All in sync. All standard tech."
47
+ iconRole="iconFirst"
48
+ items={outputs.map((item) => ({
49
+ icon: () => (
50
+ <span aria-hidden className="text-3xl">
51
+ {item.icon}
52
+ </span>
53
+ ),
54
+ title: item.title,
55
+ description: item.description,
56
+ }))}
57
+ />
58
+ );
59
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+ import { IconGridSection, type IconGridItem } from './IconGridSection';
3
+ import { AlertTriangle, Layers, RefreshCw, XCircle } from 'lucide-react';
4
+
5
+ const problemItems: IconGridItem[] = [
6
+ {
7
+ icon: AlertTriangle,
8
+ title: "Can't enforce invariants",
9
+ description:
10
+ 'AI-generated code drifts from business rules over time. No source of truth means no safety.',
11
+ iconClassName: 'text-red-400',
12
+ },
13
+ {
14
+ icon: Layers,
15
+ title: 'Multi-surface chaos',
16
+ description:
17
+ 'API, DB, UI, and events get out of sync. One change breaks three surfaces.',
18
+ iconClassName: 'text-orange-400',
19
+ },
20
+ {
21
+ icon: RefreshCw,
22
+ title: 'Hallucinated refactors',
23
+ description:
24
+ 'AI "improvements" introduce subtle bugs and break contracts you didn’t know existed.',
25
+ iconClassName: 'text-amber-400',
26
+ },
27
+ {
28
+ icon: XCircle,
29
+ title: 'Unmaintainable spaghetti',
30
+ description:
31
+ 'Teams ship fast initially, then spend months untangling AI-generated chaos.',
32
+ iconClassName: 'text-red-400',
33
+ },
34
+ ];
35
+
36
+ export function ProblemSection() {
37
+ return (
38
+ <IconGridSection
39
+ tone="muted"
40
+ columns={4}
41
+ eyebrow="The Problem"
42
+ title="AI agents write code fast. Then the chaos begins."
43
+ subtitle='In 2025, "vibe coding" and AI agents generate enormous amounts of code. But they have critical limitations that destroy long-term maintainability.'
44
+ items={problemItems}
45
+ />
46
+ );
47
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+ import { IconGridSection, type IconGridItem } from './IconGridSection';
3
+ import { FileCode, Layers, RefreshCw, Shield } from 'lucide-react';
4
+
5
+ const solutionItems: IconGridItem[] = [
6
+ {
7
+ icon: FileCode,
8
+ title: 'Canonical Source of Truth',
9
+ description:
10
+ 'Contracts define what the system should do, not just what it does. AI agents read specs, not implementations.',
11
+ iconClassName: 'text-emerald-400',
12
+ },
13
+ {
14
+ icon: Layers,
15
+ title: 'Multi-Surface Consistency',
16
+ description:
17
+ 'One spec generates API, DB, UI, events, and MCP tools. All surfaces stay in sync because they share the same source.',
18
+ iconClassName: 'text-blue-400',
19
+ },
20
+ {
21
+ icon: RefreshCw,
22
+ title: 'Safe Regeneration',
23
+ description:
24
+ 'Regenerate code anytime without fear. Specs enforce invariants. Breaking changes caught at compile time.',
25
+ iconClassName: 'text-violet-400',
26
+ },
27
+ {
28
+ icon: Shield,
29
+ title: 'AI Governance',
30
+ description:
31
+ 'Constrain what AI agents can change. Enforce contracts they must respect. Flag violations automatically.',
32
+ iconClassName: 'text-pink-400',
33
+ },
34
+ ];
35
+
36
+ export function SolutionSection() {
37
+ return (
38
+ <IconGridSection
39
+ tone="default"
40
+ columns={4}
41
+ eyebrow="The Solution"
42
+ title="ContractSpec: The safety layer for AI-coded systems"
43
+ subtitle="Define contracts once. Generate consistent code across all surfaces. Regenerate safely anytime. No lock-in."
44
+ items={solutionItems}
45
+ />
46
+ );
47
+ }
@@ -0,0 +1,55 @@
1
+ import * as React from 'react';
2
+ import { IconGridSection } from './IconGridSection';
3
+
4
+ const steps = [
5
+ {
6
+ step: 1,
7
+ title: 'Pick one module',
8
+ description:
9
+ 'Start with one API endpoint, one entity, one surface. No big-bang migration.',
10
+ },
11
+ {
12
+ step: 2,
13
+ title: 'Define the contract',
14
+ description:
15
+ 'Write a spec in TypeScript. Just types and Zod schemas you already know.',
16
+ },
17
+ {
18
+ step: 3,
19
+ title: 'Generate & compare',
20
+ description:
21
+ 'See what ContractSpec generates. Compare to your existing code. Keep what works.',
22
+ },
23
+ {
24
+ step: 4,
25
+ title: 'Expand gradually',
26
+ description:
27
+ 'Add more contracts as you see value. No pressure. No lock-in. Your pace.',
28
+ },
29
+ ];
30
+
31
+ export function StepsSection() {
32
+ return (
33
+ <IconGridSection
34
+ tone="default"
35
+ columns={4}
36
+ title="How incremental adoption works"
37
+ padding="comfortable"
38
+ iconRole="listing"
39
+ items={steps.map((item) => ({
40
+ icon: ({ className }) => (
41
+ <div
42
+ className={`bg-primary/15 flex h-10 w-10 items-center justify-center rounded-lg ${className ?? ''}`}
43
+ >
44
+ <span className="text-primary text-sm font-semibold">
45
+ {item.step}
46
+ </span>
47
+ </div>
48
+ ),
49
+ title: item.title,
50
+ description: item.description,
51
+ tone: 'muted',
52
+ }))}
53
+ />
54
+ );
55
+ }