@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,409 @@
1
+ 'use client';
2
+
3
+ import { ButtonLink, MarketingSection } from '@contractspec/lib.design-system';
4
+ import { Box, HStack, VStack } from '@contractspec/lib.ui-kit-web/ui/stack';
5
+ import {
6
+ H1,
7
+ H2,
8
+ H3,
9
+ Lead,
10
+ Muted,
11
+ Small,
12
+ } from '@contractspec/lib.ui-kit-web/ui/typography';
13
+ import {
14
+ Check,
15
+ Clock,
16
+ MapPin,
17
+ MessageSquare,
18
+ Percent,
19
+ Rocket,
20
+ Target,
21
+ Users,
22
+ X,
23
+ } from 'lucide-react';
24
+
25
+ const COFOUNDER_EMAIL = 'tboutron@contractspec.io';
26
+ const APPLY_SUBJECT = 'Co-founder application: ContractSpec';
27
+ const APPLY_BODY = `Hi Theo,
28
+
29
+ I am reaching out about co-founding ContractSpec.
30
+
31
+ LinkedIn: [your link]
32
+ Proof of work #1: [link]
33
+ Proof of work #2: [link]
34
+
35
+ Why ContractSpec:
36
+ [your answer]
37
+
38
+ What I would own in the first 90 days:
39
+ [your answer]
40
+ `;
41
+
42
+ const mailtoLink = `mailto:${COFOUNDER_EMAIL}?subject=${encodeURIComponent(APPLY_SUBJECT)}&body=${encodeURIComponent(APPLY_BODY)}`;
43
+
44
+ /* -------------------------------------------------------------------------- */
45
+ /* Section Components */
46
+ /* -------------------------------------------------------------------------- */
47
+
48
+ function HeroSection() {
49
+ return (
50
+ <MarketingSection tone="gradient" padding="spacious" align="center">
51
+ <VStack gap="lg" align="center" className="text-center">
52
+ <H1 className="text-4xl leading-tight font-bold text-balance md:text-5xl">
53
+ Co-founder wanted
54
+ </H1>
55
+ <Lead className="text-muted-foreground max-w-2xl text-lg text-balance md:text-xl">
56
+ ContractSpec is a contract-first compiler for AI-generated code.
57
+ Define specs, enforce policies, regenerate safely. Pre-PMF. Building
58
+ in public.
59
+ </Lead>
60
+ <HStack gap="md" justify="center" wrap="wrap" className="pt-2">
61
+ <ButtonLink href={mailtoLink}>Talk about co-founding</ButtonLink>
62
+ <ButtonLink variant="ghost" href="/contact">
63
+ Become a design partner
64
+ </ButtonLink>
65
+ </HStack>
66
+ </VStack>
67
+ </MarketingSection>
68
+ );
69
+ }
70
+
71
+ function WhatExistsSection() {
72
+ const realNow = [
73
+ 'ContractSpec Core: open-source spec compiler',
74
+ 'Working CLI and TypeScript runtime',
75
+ 'Design partner pipeline open',
76
+ 'Solo founder, bootstrapped',
77
+ ];
78
+
79
+ const planned = [
80
+ 'Visual studio for specs',
81
+ 'Auto-evolution engine',
82
+ 'Multi-tenant SaaS',
83
+ 'Integration marketplace',
84
+ ];
85
+
86
+ return (
87
+ <MarketingSection padding="comfortable" align="center" maxWidth="lg">
88
+ <VStack gap="lg">
89
+ <H2 className="text-3xl font-bold">What exists today</H2>
90
+ <div className="grid w-full gap-8 md:grid-cols-2">
91
+ <VStack gap="sm" align="start">
92
+ <H3 className="text-lg font-semibold text-emerald-400">Real now</H3>
93
+ <ul className="space-y-2">
94
+ {realNow.map((item) => (
95
+ <li key={item} className="flex items-start gap-2">
96
+ <Check size={16} className="mt-1 shrink-0 text-emerald-400" />
97
+ <Small>{item}</Small>
98
+ </li>
99
+ ))}
100
+ </ul>
101
+ </VStack>
102
+ <VStack gap="sm" align="start">
103
+ <H3 className="text-lg font-semibold text-blue-400">Planned</H3>
104
+ <ul className="space-y-2">
105
+ {planned.map((item) => (
106
+ <li key={item} className="flex items-start gap-2">
107
+ <Target size={16} className="mt-1 shrink-0 text-blue-400" />
108
+ <Small>{item}</Small>
109
+ </li>
110
+ ))}
111
+ </ul>
112
+ </VStack>
113
+ </div>
114
+ </VStack>
115
+ </MarketingSection>
116
+ );
117
+ }
118
+
119
+ function RoleSection() {
120
+ const gtmDeliverables = [
121
+ 'Run 5+ sales conversations per week',
122
+ 'Own the design partner pipeline end-to-end',
123
+ 'Write positioning copy that ships',
124
+ 'Build and maintain partnership channels',
125
+ 'Turn user feedback into roadmap signal',
126
+ ];
127
+
128
+ const productDeliverables = [
129
+ 'Ship UI/UX improvements weekly',
130
+ 'Define specs based on user research',
131
+ 'Own the studio experience',
132
+ 'Collaborate on architecture decisions',
133
+ ];
134
+
135
+ return (
136
+ <MarketingSection
137
+ // tone="subtle"
138
+ padding="comfortable"
139
+ align="center"
140
+ maxWidth="lg"
141
+ >
142
+ <VStack gap="lg">
143
+ <H2 className="text-3xl font-bold">The role</H2>
144
+ <VStack gap="md" align="start" className="w-full">
145
+ <H3 className="text-xl font-semibold">
146
+ Option A: GTM / Sales / Partnerships
147
+ </H3>
148
+ <Muted>Weekly deliverables, not vague traits:</Muted>
149
+ <ul className="space-y-2">
150
+ {gtmDeliverables.map((item) => (
151
+ <li key={item} className="flex items-start gap-2">
152
+ <Rocket size={16} className="mt-1 shrink-0 text-amber-400" />
153
+ <Small>{item}</Small>
154
+ </li>
155
+ ))}
156
+ </ul>
157
+ </VStack>
158
+ <VStack gap="md" align="start" className="w-full pt-4">
159
+ <H3 className="text-xl font-semibold">Option B: Product / Design</H3>
160
+ <Muted>If this is your strength:</Muted>
161
+ <ul className="space-y-2">
162
+ {productDeliverables.map((item) => (
163
+ <li key={item} className="flex items-start gap-2">
164
+ <Rocket size={16} className="mt-1 shrink-0 text-purple-400" />
165
+ <Small>{item}</Small>
166
+ </li>
167
+ ))}
168
+ </ul>
169
+ </VStack>
170
+ </VStack>
171
+ </MarketingSection>
172
+ );
173
+ }
174
+
175
+ function IdealCofounderSection() {
176
+ const qualities = [
177
+ "You have shipped products people paid for — links or it didn't happen",
178
+ 'You have sold something (product, consulting, yourself)',
179
+ 'You write clearly and fast — emails, docs, copy',
180
+ 'You have taste: you know good UX when you see it',
181
+ 'You can work 6+ months without a salary',
182
+ 'You are allergic to meetings that could be docs',
183
+ 'You have built in public or contributed to open source',
184
+ 'You are based in Europe or overlap significantly with CET',
185
+ ];
186
+
187
+ return (
188
+ <MarketingSection padding="comfortable" align="center" maxWidth="lg">
189
+ <VStack gap="lg">
190
+ <H2 className="text-3xl font-bold">The ideal co-founder</H2>
191
+ <ul className="space-y-3">
192
+ {qualities.map((item) => (
193
+ <li key={item} className="flex items-start gap-2">
194
+ <Check size={16} className="mt-1 shrink-0 text-emerald-400" />
195
+ <Small>{item}</Small>
196
+ </li>
197
+ ))}
198
+ </ul>
199
+ <Box className="border-border mt-4 rounded-lg border p-4">
200
+ <VStack gap="sm" align="start">
201
+ <H3 className="text-lg font-semibold">Proof of work examples</H3>
202
+ <Muted className="text-sm">
203
+ GitHub profile, shipped product, writing (blog/Twitter/essays),
204
+ revenue screenshot, open-source contributions, or anything that
205
+ shows you execute.
206
+ </Muted>
207
+ </VStack>
208
+ </Box>
209
+ </VStack>
210
+ </MarketingSection>
211
+ );
212
+ }
213
+
214
+ function WhatYouGetSection() {
215
+ const benefits = [
216
+ {
217
+ icon: <Percent size={20} className="text-emerald-400" />,
218
+ title: 'Equity-first',
219
+ desc: 'Meaningful co-founder equity. Salary is minimal/zero until revenue covers it.',
220
+ },
221
+ {
222
+ icon: <Users size={20} className="text-blue-400" />,
223
+ title: 'Real ownership',
224
+ desc: 'You own your domain. No permission-seeking. Ship and iterate.',
225
+ },
226
+ {
227
+ icon: <MessageSquare size={20} className="text-amber-400" />,
228
+ title: 'Written-first decisions',
229
+ desc: 'We default to async, docs, and fast decisions. Meetings are last resort.',
230
+ },
231
+ ];
232
+
233
+ const values = [
234
+ 'Contracts over conventions',
235
+ 'Clarity over cleverness',
236
+ 'Safety over speed (in code)',
237
+ 'Leverage over labor',
238
+ ];
239
+
240
+ return (
241
+ <MarketingSection
242
+ // tone="subtle"
243
+ padding="comfortable"
244
+ align="center"
245
+ maxWidth="lg"
246
+ >
247
+ <VStack gap="lg">
248
+ <H2 className="text-3xl font-bold">What you get</H2>
249
+ <div className="grid w-full gap-6 md:grid-cols-3">
250
+ {benefits.map((b) => (
251
+ <VStack
252
+ key={b.title}
253
+ gap="sm"
254
+ align="start"
255
+ className="border-border rounded-lg border p-4"
256
+ >
257
+ {b.icon}
258
+ <H3 className="text-lg font-semibold">{b.title}</H3>
259
+ <Muted className="text-sm">{b.desc}</Muted>
260
+ </VStack>
261
+ ))}
262
+ </div>
263
+ <VStack gap="sm" align="start" className="w-full pt-4">
264
+ <H3 className="text-lg font-semibold">Our values</H3>
265
+ <HStack gap="sm" wrap="wrap">
266
+ {values.map((v) => (
267
+ <Box
268
+ key={v}
269
+ className="border-border rounded-full border px-3 py-1 text-sm"
270
+ >
271
+ {v}
272
+ </Box>
273
+ ))}
274
+ </HStack>
275
+ </VStack>
276
+ </VStack>
277
+ </MarketingSection>
278
+ );
279
+ }
280
+
281
+ function RedFlagsSection() {
282
+ const redFlags = [
283
+ 'Needs a big salary now',
284
+ 'Hates selling or talking to users',
285
+ 'Vague about past execution',
286
+ 'Wants to "advise" instead of build',
287
+ 'Needs a big team to feel productive',
288
+ 'Cannot write clearly',
289
+ ];
290
+
291
+ return (
292
+ <MarketingSection padding="comfortable" align="center" maxWidth="lg">
293
+ <VStack gap="lg">
294
+ <H2 className="text-3xl font-bold">Non-negotiables / red flags</H2>
295
+ <Muted>If any of these apply, this is not the right fit:</Muted>
296
+ <ul className="space-y-2">
297
+ {redFlags.map((item) => (
298
+ <li key={item} className="flex items-start gap-2">
299
+ <X size={16} className="mt-1 shrink-0 text-red-400" />
300
+ <Small>{item}</Small>
301
+ </li>
302
+ ))}
303
+ </ul>
304
+ </VStack>
305
+ </MarketingSection>
306
+ );
307
+ }
308
+
309
+ function FAQSection() {
310
+ const faqs = [
311
+ {
312
+ icon: <Users size={18} />,
313
+ q: 'Why co-founder instead of hiring?',
314
+ a: "I need a partner who thinks like an owner, not an employee. Someone who will stay when things get hard and share in the upside when they don't.",
315
+ },
316
+ {
317
+ icon: <Clock size={18} />,
318
+ q: 'What is the timeline to revenue?',
319
+ a: 'Design partners are converting now. Goal: paying customers in 2025. But this is startup life — timelines are best guesses.',
320
+ },
321
+ {
322
+ icon: <MapPin size={18} />,
323
+ q: 'Is this remote?',
324
+ a: 'Yes. Async-first. Occasional in-person (Paris-based) for planning. Europe timezone overlap strongly preferred.',
325
+ },
326
+ {
327
+ icon: <Percent size={18} />,
328
+ q: 'How much equity?',
329
+ a: 'Depends on what you bring, when you join, and how much you can commit. Expect meaningful co-founder equity with 4-year vesting. We will discuss specifics in person.',
330
+ },
331
+ ];
332
+
333
+ return (
334
+ <MarketingSection
335
+ // tone="subtle"
336
+ padding="comfortable"
337
+ align="center"
338
+ maxWidth="lg"
339
+ >
340
+ <VStack gap="lg">
341
+ <H2 className="text-3xl font-bold">FAQ</H2>
342
+ <VStack gap="md" className="w-full">
343
+ {faqs.map((faq) => (
344
+ <VStack
345
+ key={faq.q}
346
+ gap="xs"
347
+ align="start"
348
+ className="border-border w-full rounded-lg border p-4"
349
+ >
350
+ <HStack gap="sm" align="center">
351
+ <span className="text-muted-foreground">{faq.icon}</span>
352
+ <H3 className="text-lg font-semibold">{faq.q}</H3>
353
+ </HStack>
354
+ <Muted>{faq.a}</Muted>
355
+ </VStack>
356
+ ))}
357
+ </VStack>
358
+ </VStack>
359
+ </MarketingSection>
360
+ );
361
+ }
362
+
363
+ function FinalCtaSection() {
364
+ return (
365
+ <MarketingSection
366
+ tone="gradient"
367
+ padding="comfortable"
368
+ align="center"
369
+ maxWidth="lg"
370
+ >
371
+ <VStack gap="md" align="center" className="text-center">
372
+ <H2 className="text-3xl font-bold md:text-4xl">Ready to talk?</H2>
373
+ <Lead className="text-muted-foreground max-w-xl">
374
+ Send an email with: your LinkedIn, 2 proof-of-work links, why
375
+ ContractSpec, and what you would own in the first 90 days.
376
+ </Lead>
377
+ <HStack gap="md" justify="center" wrap="wrap" className="pt-2">
378
+ <ButtonLink href={mailtoLink}>Talk about co-founding</ButtonLink>
379
+ <ButtonLink variant="ghost" href="/contact">
380
+ Become a design partner
381
+ </ButtonLink>
382
+ </HStack>
383
+ <Muted className="pt-4 text-sm">
384
+ CHAMAN VENTURES, SASU · RCS Paris · SIREN 989 498 902 · 229 rue
385
+ Saint-Honoré, 75001 Paris
386
+ </Muted>
387
+ </VStack>
388
+ </MarketingSection>
389
+ );
390
+ }
391
+
392
+ /* -------------------------------------------------------------------------- */
393
+ /* Main Component */
394
+ /* -------------------------------------------------------------------------- */
395
+
396
+ export function CofounderPage() {
397
+ return (
398
+ <VStack as="main" gap="none">
399
+ <HeroSection />
400
+ <WhatExistsSection />
401
+ <RoleSection />
402
+ <IdealCofounderSection />
403
+ <WhatYouGetSection />
404
+ <RedFlagsSection />
405
+ <FAQSection />
406
+ <FinalCtaSection />
407
+ </VStack>
408
+ );
409
+ }
@@ -0,0 +1,174 @@
1
+ 'use client';
2
+
3
+ import { useActionState } from 'react';
4
+ import {
5
+ Calendar,
6
+ MessageSquare,
7
+ CheckCircle,
8
+ AlertCircle,
9
+ } from 'lucide-react';
10
+ import { submitContactForm } from '../../libs/email/contact';
11
+ import type { SubmitContactFormResult } from '../../libs/email/types'; // Assuming these are exported from root or similar, need to check where submitContactForm lives.
12
+ // Wait check imports again. submitContactForm is imported from @contractspec/bundle.marketing.
13
+ // In bundle.marketing, it is likely in 'src/actions' or 'src/utils'.
14
+ // I need to check where submitContactForm is defined in bundle.marketing.
15
+ import { WaitlistSection } from './waitlist-section';
16
+ import {
17
+ ActionForm,
18
+ Button,
19
+ Input,
20
+ Textarea,
21
+ } from '@contractspec/lib.design-system';
22
+ import { VStack, HStack } from '@contractspec/lib.ui-kit-web/ui/stack';
23
+ import {
24
+ H2,
25
+ H1,
26
+ Small,
27
+ Muted,
28
+ } from '@contractspec/lib.ui-kit-web/ui/typography';
29
+
30
+ export function ContactClient() {
31
+ // Contact form handler
32
+ const handleContactSubmit = async (
33
+ _prevState: SubmitContactFormResult | null,
34
+ formData: FormData
35
+ ): Promise<SubmitContactFormResult> => {
36
+ const result = await submitContactForm(formData);
37
+
38
+ if (result.success) {
39
+ return {
40
+ success: true,
41
+ text: "Message sent successfully! We'll get back to you soon.",
42
+ };
43
+ } else {
44
+ return {
45
+ success: false,
46
+ text: result.text || 'Failed to send message. Please try again.',
47
+ };
48
+ }
49
+ };
50
+
51
+ const [contactResult, contactAction, contactPending] = useActionState<
52
+ SubmitContactFormResult | null,
53
+ FormData
54
+ >(handleContactSubmit, null);
55
+
56
+ return (
57
+ <section className="section-padding hero-gradient w-full">
58
+ <VStack className="mx-auto max-w-4xl gap-16">
59
+ <VStack className="gap-4 text-center">
60
+ <H1 className="text-5xl font-bold">Get in touch</H1>
61
+ <Muted className="text-lg">
62
+ Choose how you'd like to connect with us
63
+ </Muted>
64
+ </VStack>
65
+
66
+ {/* Waitlist Registration Section */}
67
+ <WaitlistSection context="contact" />
68
+
69
+ {/* Book a Call Section */}
70
+ <VStack className="card-subtle gap-6 p-8" id="call">
71
+ <HStack className="items-center gap-3">
72
+ <Calendar className="text-blue-400" size={24} />
73
+ <VStack className="items-start gap-1">
74
+ <H2 className="text-2xl font-bold">Book a 20-min call</H2>
75
+ <Muted className="text-sm">
76
+ Schedule a walkthrough with our team to see ContractSpec in
77
+ action
78
+ </Muted>
79
+ </VStack>
80
+ </HStack>
81
+
82
+ <div className="border-border overflow-hidden rounded-lg border">
83
+ <object
84
+ data="https://meet.reclaimai.com/e/f863cb29-caac-44b6-972b-1407dd9545a3"
85
+ width="100%"
86
+ height="700px"
87
+ style={{ outline: 'none' }}
88
+ aria-label="Calendar booking widget"
89
+ />
90
+ </div>
91
+ </VStack>
92
+
93
+ {/* Send Message Section */}
94
+ <VStack className="card-subtle gap-6 p-8" id="message">
95
+ <HStack className="items-center gap-3">
96
+ <MessageSquare className="text-emerald-400" size={24} />
97
+ <VStack className="items-start gap-1">
98
+ <H2 className="text-2xl font-bold">Send us a message</H2>
99
+ <Muted className="text-sm">
100
+ Have questions or feedback? We'd love to hear from you
101
+ </Muted>
102
+ </VStack>
103
+ </HStack>
104
+
105
+ <ActionForm action={contactAction}>
106
+ <VStack className="gap-4">
107
+ <VStack className="gap-2">
108
+ <Small className="text-sm font-medium">Name</Small>
109
+ <Input
110
+ id="contact-name"
111
+ name="name"
112
+ type="text"
113
+ placeholder="Your name"
114
+ disabled={contactPending || contactResult?.success}
115
+ required
116
+ />
117
+ </VStack>
118
+
119
+ <VStack className="gap-2">
120
+ <Small className="text-sm font-medium">Email</Small>
121
+ <Input
122
+ id="contact-email"
123
+ name="email"
124
+ type="email"
125
+ keyboard={{ kind: 'email' }}
126
+ placeholder="your@email.com"
127
+ disabled={contactPending || contactResult?.success}
128
+ required
129
+ />
130
+ </VStack>
131
+
132
+ <VStack className="gap-2">
133
+ <Small className="text-sm font-medium">Message</Small>
134
+ <Textarea
135
+ id="contact-message"
136
+ name="message"
137
+ placeholder="Tell us what's on your mind..."
138
+ disabled={contactPending || contactResult?.success}
139
+ rows={6}
140
+ required
141
+ />
142
+ </VStack>
143
+
144
+ {contactResult && !contactPending && (
145
+ <HStack
146
+ className={`items-center gap-2 rounded-lg p-3 text-sm ${
147
+ contactResult.success
148
+ ? 'border border-green-500/20 bg-green-500/10 text-green-400'
149
+ : 'border border-red-500/20 bg-red-500/10 text-red-400'
150
+ }`}
151
+ >
152
+ {contactResult.success ? (
153
+ <CheckCircle size={16} />
154
+ ) : (
155
+ <AlertCircle size={16} />
156
+ )}
157
+ <Small>{contactResult.text}</Small>
158
+ </HStack>
159
+ )}
160
+
161
+ <Button
162
+ type="submit"
163
+ disabled={contactPending || contactResult?.success}
164
+ className="w-full"
165
+ >
166
+ {contactPending ? 'Sending...' : 'Send message'}
167
+ </Button>
168
+ </VStack>
169
+ </ActionForm>
170
+ </VStack>
171
+ </VStack>
172
+ </section>
173
+ );
174
+ }