@contractspec/bundle.marketing 3.7.6 → 3.7.7
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/.turbo/turbo-build.log +84 -84
- package/AGENTS.md +29 -21
- package/README.md +36 -49
- package/dist/browser/components/marketing/ChangelogPage.js +8 -8
- package/dist/browser/components/marketing/CofounderPage.js +167 -523
- package/dist/browser/components/marketing/ContactClient.js +200 -207
- package/dist/browser/components/marketing/ContributePage.js +211 -463
- package/dist/browser/components/marketing/DesignPartnerPage.js +165 -218
- package/dist/browser/components/marketing/LandingPage.js +464 -568
- package/dist/browser/components/marketing/PricingClient.js +213 -839
- package/dist/browser/components/marketing/ProductClientPage.js +265 -463
- package/dist/browser/components/marketing/index.js +2007 -3338
- package/dist/browser/components/marketing/pricing-thinking-modal.js +12 -12
- package/dist/browser/components/marketing/sections/AudienceSection.js +2 -2
- package/dist/browser/components/marketing/sections/CorePositioningSection.js +2 -2
- package/dist/browser/components/marketing/sections/CtaSection.js +3 -3
- package/dist/browser/components/marketing/sections/FearsSection.js +3 -3
- package/dist/browser/components/marketing/sections/HeroMarketingSection.js +6 -6
- package/dist/browser/components/marketing/sections/IconGridSection.js +2 -2
- package/dist/browser/components/marketing/sections/OutputsSection.js +2 -2
- package/dist/browser/components/marketing/sections/ProblemSection.js +2 -2
- package/dist/browser/components/marketing/sections/SolutionSection.js +2 -2
- package/dist/browser/components/marketing/sections/StepsSection.js +4 -4
- package/dist/browser/components/marketing/studio-signup-section.js +25 -41
- package/dist/browser/components/templates/TemplatesClientPage.js +2324 -3578
- package/dist/browser/components/templates/TemplatesPage.js +1 -1
- package/dist/browser/components/templates/TemplatesPreviewModal.js +3 -3
- package/dist/browser/components/templates/index.js +2361 -3615
- package/dist/browser/index.js +2363 -3617
- package/dist/browser/libs/email/client.js +1 -1
- package/dist/browser/libs/email/contact.js +1 -1
- package/dist/browser/libs/email/newsletter.js +1 -1
- package/dist/browser/libs/email/waitlist-application.js +1 -1
- package/dist/browser/libs/email/waitlist.js +1 -1
- package/dist/browser/registry/engine.js +2003 -3334
- package/dist/browser/registry/index.js +2003 -3334
- package/dist/browser/registry/registry-docs.js +2 -2
- package/dist/browser/registry/registry-landing.js +2007 -3338
- package/dist/browser/registry/registry.js +2003 -3334
- package/dist/browser/registry/utils.js +2003 -3334
- package/dist/components/marketing/ChangelogPage.js +8 -8
- package/dist/components/marketing/CofounderPage.js +167 -523
- package/dist/components/marketing/ContactClient.js +200 -207
- package/dist/components/marketing/ContributePage.d.ts +0 -2
- package/dist/components/marketing/ContributePage.js +211 -463
- package/dist/components/marketing/DesignPartnerPage.js +165 -218
- package/dist/components/marketing/LandingPage.js +464 -568
- package/dist/components/marketing/PricingClient.js +213 -839
- package/dist/components/marketing/ProductClientPage.js +265 -463
- package/dist/components/marketing/index.d.ts +5 -5
- package/dist/components/marketing/index.js +2007 -3338
- package/dist/components/marketing/pricing-thinking-modal.js +12 -12
- package/dist/components/marketing/sections/AudienceSection.js +2 -2
- package/dist/components/marketing/sections/CorePositioningSection.js +2 -2
- package/dist/components/marketing/sections/CtaSection.js +3 -3
- package/dist/components/marketing/sections/FearsSection.js +3 -3
- package/dist/components/marketing/sections/HeroMarketingSection.js +6 -6
- package/dist/components/marketing/sections/IconGridSection.d.ts +3 -3
- package/dist/components/marketing/sections/IconGridSection.js +2 -2
- package/dist/components/marketing/sections/OutputsSection.js +2 -2
- package/dist/components/marketing/sections/ProblemSection.js +2 -2
- package/dist/components/marketing/sections/SolutionSection.js +2 -2
- package/dist/components/marketing/sections/StepsSection.js +4 -4
- package/dist/components/marketing/studio-signup-section.js +25 -41
- package/dist/components/templates/TemplatesClientPage.js +2324 -3578
- package/dist/components/templates/TemplatesPage.js +1 -1
- package/dist/components/templates/TemplatesPreviewModal.js +3 -3
- package/dist/components/templates/index.js +2361 -3615
- package/dist/index.js +2363 -3617
- package/dist/libs/email/client.js +1 -1
- package/dist/libs/email/contact.js +1 -1
- package/dist/libs/email/newsletter.js +1 -1
- package/dist/libs/email/waitlist-application.js +1 -1
- package/dist/libs/email/waitlist.js +1 -1
- package/dist/node/components/marketing/ChangelogPage.js +8 -8
- package/dist/node/components/marketing/CofounderPage.js +167 -523
- package/dist/node/components/marketing/ContactClient.js +200 -207
- package/dist/node/components/marketing/ContributePage.js +211 -463
- package/dist/node/components/marketing/DesignPartnerPage.js +165 -218
- package/dist/node/components/marketing/LandingPage.js +464 -568
- package/dist/node/components/marketing/PricingClient.js +213 -839
- package/dist/node/components/marketing/ProductClientPage.js +265 -463
- package/dist/node/components/marketing/index.js +2007 -3338
- package/dist/node/components/marketing/pricing-thinking-modal.js +12 -12
- package/dist/node/components/marketing/sections/AudienceSection.js +2 -2
- package/dist/node/components/marketing/sections/CorePositioningSection.js +2 -2
- package/dist/node/components/marketing/sections/CtaSection.js +3 -3
- package/dist/node/components/marketing/sections/FearsSection.js +3 -3
- package/dist/node/components/marketing/sections/HeroMarketingSection.js +6 -6
- package/dist/node/components/marketing/sections/IconGridSection.js +2 -2
- package/dist/node/components/marketing/sections/OutputsSection.js +2 -2
- package/dist/node/components/marketing/sections/ProblemSection.js +2 -2
- package/dist/node/components/marketing/sections/SolutionSection.js +2 -2
- package/dist/node/components/marketing/sections/StepsSection.js +4 -4
- package/dist/node/components/marketing/studio-signup-section.js +25 -41
- package/dist/node/components/templates/TemplatesClientPage.js +2324 -3578
- package/dist/node/components/templates/TemplatesPage.js +1 -1
- package/dist/node/components/templates/TemplatesPreviewModal.js +3 -3
- package/dist/node/components/templates/index.js +2361 -3615
- package/dist/node/index.js +2363 -3617
- package/dist/node/libs/email/client.js +1 -1
- package/dist/node/libs/email/contact.js +1 -1
- package/dist/node/libs/email/newsletter.js +1 -1
- package/dist/node/libs/email/waitlist-application.js +1 -1
- package/dist/node/libs/email/waitlist.js +1 -1
- package/dist/node/registry/engine.js +2003 -3334
- package/dist/node/registry/index.js +2003 -3334
- package/dist/node/registry/registry-docs.js +2 -2
- package/dist/node/registry/registry-landing.js +2007 -3338
- package/dist/node/registry/registry.js +2003 -3334
- package/dist/node/registry/utils.js +2003 -3334
- package/dist/registry/engine.js +2003 -3334
- package/dist/registry/index.js +2003 -3334
- package/dist/registry/registry-docs.js +2 -2
- package/dist/registry/registry-landing.js +2007 -3338
- package/dist/registry/registry.js +2003 -3334
- package/dist/registry/utils.js +2003 -3334
- package/package.json +22 -22
- package/src/bundles/MarketingBundle.ts +273 -273
- package/src/components/marketing/ChangelogPage.tsx +72 -100
- package/src/components/marketing/CofounderPage.tsx +120 -384
- package/src/components/marketing/ContactClient.tsx +164 -154
- package/src/components/marketing/ContributePage.tsx +139 -313
- package/src/components/marketing/DesignPartnerPage.tsx +133 -171
- package/src/components/marketing/LandingPage.tsx +353 -25
- package/src/components/marketing/PricingClient.tsx +192 -437
- package/src/components/marketing/ProductClientPage.tsx +255 -377
- package/src/components/marketing/index.ts +5 -5
- package/src/components/marketing/pricing-thinking-modal.tsx +197 -197
- package/src/components/marketing/sections/AudienceSection.tsx +55 -56
- package/src/components/marketing/sections/CorePositioningSection.tsx +37 -37
- package/src/components/marketing/sections/CtaSection.tsx +49 -50
- package/src/components/marketing/sections/DevelopersSection.tsx +26 -27
- package/src/components/marketing/sections/FearsSection.tsx +36 -37
- package/src/components/marketing/sections/HeroMarketingSection.tsx +59 -59
- package/src/components/marketing/sections/IconGridSection.tsx +71 -71
- package/src/components/marketing/sections/OutputsSection.tsx +51 -52
- package/src/components/marketing/sections/ProblemSection.tsx +39 -40
- package/src/components/marketing/sections/SolutionSection.tsx +39 -40
- package/src/components/marketing/sections/StepsSection.tsx +47 -48
- package/src/components/marketing/studio-signup-section.tsx +39 -41
- package/src/components/templates/TemplatesClientPage.tsx +727 -685
- package/src/components/templates/TemplatesPage.tsx +110 -110
- package/src/components/templates/TemplatesPreviewModal.tsx +197 -198
- package/src/index.ts +4 -4
- package/src/libs/email/client.test.ts +81 -81
- package/src/libs/email/client.ts +111 -111
- package/src/libs/email/contact.ts +35 -35
- package/src/libs/email/newsletter.ts +46 -46
- package/src/libs/email/types.ts +29 -29
- package/src/libs/email/utils.ts +5 -5
- package/src/libs/email/waitlist-application.ts +72 -72
- package/src/libs/email/waitlist.ts +46 -46
- package/src/libs/pricing-examples.ts +12 -12
- package/src/registry/engine.ts +16 -16
- package/src/registry/factory.ts +57 -57
- package/src/registry/registry-docs.ts +656 -666
- package/src/registry/registry-landing.ts +94 -95
- package/src/registry/registry.ts +36 -37
- package/src/registry/types.ts +2 -2
- package/src/registry/utils.ts +56 -56
- package/tsconfig.json +11 -11
- package/tsdown.config.js +5 -5
|
@@ -1,714 +1,756 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import {
|
|
4
|
+
analyticsEventNames,
|
|
5
|
+
captureAnalyticsEvent,
|
|
6
|
+
} from '@contractspec/bundle.library/libs/posthog/client';
|
|
7
7
|
import type {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
RegistryTemplate,
|
|
9
|
+
TemplateId,
|
|
10
10
|
} from '@contractspec/lib.example-shared-ui';
|
|
11
11
|
import { useRegistryTemplates } from '@contractspec/lib.example-shared-ui';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
Tooltip,
|
|
15
|
-
TooltipContent,
|
|
16
|
-
TooltipProvider,
|
|
17
|
-
TooltipTrigger,
|
|
18
|
-
} from '@contractspec/lib.ui-kit-web/ui/tooltip';
|
|
19
|
-
import {
|
|
20
|
-
analyticsEventNames,
|
|
21
|
-
captureAnalyticsEvent,
|
|
22
|
-
} from '@contractspec/bundle.library/libs/posthog/client';
|
|
12
|
+
import { cn } from '@contractspec/lib.ui-kit-core/utils';
|
|
23
13
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
Dialog,
|
|
15
|
+
DialogContent,
|
|
16
|
+
DialogDescription,
|
|
17
|
+
DialogHeader,
|
|
18
|
+
DialogTitle,
|
|
29
19
|
} from '@contractspec/lib.ui-kit-web/ui/dialog';
|
|
20
|
+
import {
|
|
21
|
+
Tooltip,
|
|
22
|
+
TooltipContent,
|
|
23
|
+
TooltipProvider,
|
|
24
|
+
TooltipTrigger,
|
|
25
|
+
} from '@contractspec/lib.ui-kit-web/ui/tooltip';
|
|
26
|
+
import { getTemplate } from '@contractspec/module.examples';
|
|
27
|
+
import { Search } from 'lucide-react';
|
|
28
|
+
import Link from 'next/link';
|
|
29
|
+
import { useState } from 'react';
|
|
30
30
|
import { StudioSignupSection } from '../marketing';
|
|
31
31
|
import { TemplatePreviewModal } from './TemplatesPreviewModal';
|
|
32
32
|
|
|
33
33
|
const templates = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
34
|
+
{
|
|
35
|
+
id: 'minimal-example',
|
|
36
|
+
templateId: 'todos-app' as TemplateId,
|
|
37
|
+
title: 'Minimal Example',
|
|
38
|
+
description:
|
|
39
|
+
'A minimal template to get you running in minutes. Perfect for exploring the engine.',
|
|
40
|
+
tags: ['Getting Started'],
|
|
41
|
+
capabilities: 'Basic Forms, Auth',
|
|
42
|
+
isStarter: true,
|
|
43
|
+
previewUrl: '/sandbox?template=minimal-example',
|
|
44
|
+
docsUrl: '/docs/getting-started/hello-world',
|
|
45
|
+
},
|
|
46
|
+
// ============================================
|
|
47
|
+
// Phase 1 Examples (using cross-cutting modules)
|
|
48
|
+
// ============================================
|
|
49
|
+
{
|
|
50
|
+
id: 'saas-boilerplate',
|
|
51
|
+
templateId: 'saas-boilerplate' as TemplateId,
|
|
52
|
+
title: 'SaaS Boilerplate',
|
|
53
|
+
description:
|
|
54
|
+
'Complete SaaS foundation with multi-tenant orgs, projects, settings, and billing usage.',
|
|
55
|
+
tags: ['Getting Started', 'SaaS', 'Business'],
|
|
56
|
+
capabilities: 'Multi-tenancy, RBAC, Projects, Billing',
|
|
57
|
+
isNew: true,
|
|
58
|
+
previewUrl: '/sandbox?template=saas-boilerplate',
|
|
59
|
+
docsUrl: '/docs/templates/saas-boilerplate',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'crm-pipeline',
|
|
63
|
+
templateId: 'crm-pipeline' as TemplateId,
|
|
64
|
+
title: 'CRM Pipeline',
|
|
65
|
+
description:
|
|
66
|
+
'Sales CRM with contacts, companies, deals, pipeline stages, and task management.',
|
|
67
|
+
tags: ['CRM', 'Business'],
|
|
68
|
+
capabilities: 'Contacts, Deals, Pipelines, Tasks',
|
|
69
|
+
isNew: true,
|
|
70
|
+
previewUrl: '/sandbox?template=crm-pipeline',
|
|
71
|
+
docsUrl: '/docs/templates/crm-pipeline',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'agent-console',
|
|
75
|
+
templateId: 'agent-console' as TemplateId,
|
|
76
|
+
title: 'AI Agent Console',
|
|
77
|
+
description:
|
|
78
|
+
'AI agent orchestration platform with tools, agents, runs, and execution logs.',
|
|
79
|
+
tags: ['AI', 'Ops'],
|
|
80
|
+
capabilities: 'Tools, Agents, Runs, Metrics',
|
|
81
|
+
isNew: true,
|
|
82
|
+
previewUrl: '/sandbox?template=agent-console',
|
|
83
|
+
docsUrl: '/docs/templates/agent-console',
|
|
84
|
+
},
|
|
85
|
+
// ============================================
|
|
86
|
+
// Phase 2-4 Examples
|
|
87
|
+
// ============================================
|
|
88
|
+
{
|
|
89
|
+
id: 'workflow-system',
|
|
90
|
+
templateId: 'workflow-system' as TemplateId,
|
|
91
|
+
title: 'Workflow / Approval System',
|
|
92
|
+
description:
|
|
93
|
+
'Multi-step workflows with role-based approvals and state transitions.',
|
|
94
|
+
tags: ['Business', 'Ops'],
|
|
95
|
+
capabilities: 'Workflows, Approvals, State Machine',
|
|
96
|
+
isNew: true,
|
|
97
|
+
previewUrl: '/sandbox?template=workflow-system',
|
|
98
|
+
docsUrl: '/docs/templates/workflow-system',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: 'marketplace',
|
|
102
|
+
templateId: 'marketplace' as TemplateId,
|
|
103
|
+
title: 'Marketplace',
|
|
104
|
+
description:
|
|
105
|
+
'Two-sided marketplace with stores, products, orders, and payouts.',
|
|
106
|
+
tags: ['Business', 'Payments'],
|
|
107
|
+
capabilities: 'Stores, Products, Orders, Payouts',
|
|
108
|
+
isNew: true,
|
|
109
|
+
previewUrl: '/sandbox?template=marketplace',
|
|
110
|
+
docsUrl: '/docs/templates/marketplace',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'integration-hub',
|
|
114
|
+
templateId: 'integration-hub' as TemplateId,
|
|
115
|
+
title: 'Integration Hub',
|
|
116
|
+
description:
|
|
117
|
+
'Third-party integrations with connections, sync configs, and field mapping.',
|
|
118
|
+
tags: ['Ops', 'AI'],
|
|
119
|
+
capabilities: 'Integrations, Connections, Sync',
|
|
120
|
+
isNew: true,
|
|
121
|
+
previewUrl: '/sandbox?template=integration-hub',
|
|
122
|
+
docsUrl: '/docs/templates/integration-hub',
|
|
123
|
+
},
|
|
124
|
+
// ============================================
|
|
125
|
+
// Learning Journeys
|
|
126
|
+
// ============================================
|
|
127
|
+
{
|
|
128
|
+
id: 'learning-journey-studio-onboarding',
|
|
129
|
+
templateId: 'learning-journey-studio-onboarding' as TemplateId,
|
|
130
|
+
title: 'Learning Journey — Studio Getting Started',
|
|
131
|
+
description:
|
|
132
|
+
'First 30 minutes in Studio: choose template, edit spec, regenerate, playground, evolution.',
|
|
133
|
+
tags: ['Learning', 'Onboarding'],
|
|
134
|
+
capabilities: 'Spec-first onboarding, XP/streak, progress widget',
|
|
135
|
+
isNew: true,
|
|
136
|
+
previewUrl: '/sandbox?template=learning-journey-studio-onboarding',
|
|
137
|
+
docsUrl: '/docs/templates/learning-journey-studio-onboarding',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: 'learning-journey-platform-tour',
|
|
141
|
+
templateId: 'learning-journey-platform-tour' as TemplateId,
|
|
142
|
+
title: 'Learning Journey — Platform Primitives Tour',
|
|
143
|
+
description:
|
|
144
|
+
'Touch identity, audit, notifications, jobs, flags, files, metering once with guided steps.',
|
|
145
|
+
tags: ['Learning', 'Platform'],
|
|
146
|
+
capabilities: 'Cross-module tour with event-driven completion',
|
|
147
|
+
isNew: true,
|
|
148
|
+
previewUrl: '/sandbox?template=learning-journey-platform-tour',
|
|
149
|
+
docsUrl: '/docs/templates/learning-journey-platform-tour',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: 'learning-journey-crm-onboarding',
|
|
153
|
+
templateId: 'learning-journey-crm-onboarding' as TemplateId,
|
|
154
|
+
title: 'Learning Journey — CRM First Win',
|
|
155
|
+
description:
|
|
156
|
+
'Get to first closed-won deal: pipeline, contact/company, deal, stages, follow-up.',
|
|
157
|
+
tags: ['Learning', 'CRM'],
|
|
158
|
+
capabilities: 'CRM onboarding with XP/streak/badge',
|
|
159
|
+
isNew: true,
|
|
160
|
+
previewUrl: '/sandbox?template=learning-journey-crm-onboarding',
|
|
161
|
+
docsUrl: '/docs/templates/learning-journey-crm-onboarding',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'analytics-dashboard',
|
|
165
|
+
templateId: 'analytics-dashboard' as TemplateId,
|
|
166
|
+
title: 'Analytics Dashboard',
|
|
167
|
+
description:
|
|
168
|
+
'Custom dashboards with widgets, saved queries, and real-time visualization.',
|
|
169
|
+
tags: ['Business', 'Ops'],
|
|
170
|
+
capabilities: 'Dashboards, Widgets, Queries',
|
|
171
|
+
isNew: true,
|
|
172
|
+
previewUrl: '/sandbox?template=analytics-dashboard',
|
|
173
|
+
docsUrl: '/docs/templates/analytics-dashboard',
|
|
174
|
+
},
|
|
175
|
+
// ============================================
|
|
176
|
+
// Classic Templates
|
|
177
|
+
// ============================================
|
|
178
|
+
{
|
|
179
|
+
id: 'plumber-ops',
|
|
180
|
+
templateId: 'messaging-app' as TemplateId,
|
|
181
|
+
title: 'Plumber Ops',
|
|
182
|
+
description:
|
|
183
|
+
'Complete workflow: Quotes → Deposit → Job → Invoice → Payment. Policy-enforced approvals.',
|
|
184
|
+
tags: ['Trades', 'Payments'],
|
|
185
|
+
capabilities: 'Quotes, Jobs, Invoicing, Payments',
|
|
186
|
+
previewUrl: '/sandbox?template=plumber-ops',
|
|
187
|
+
docsUrl: '/docs/specs/workflows',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: 'coliving-management',
|
|
191
|
+
templateId: 'recipe-app-i18n' as TemplateId,
|
|
192
|
+
title: 'Coliving Management',
|
|
193
|
+
description:
|
|
194
|
+
'Coliving management: Onboarding, chores, shared wallet. Multi-party approvals built-in.',
|
|
195
|
+
tags: ['Coliving', 'Finance'],
|
|
196
|
+
capabilities: 'Tasks, Approvals, Payments',
|
|
197
|
+
previewUrl: '/sandbox?template=coliving-management',
|
|
198
|
+
docsUrl: '/docs/specs/workflows',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: 'chores-allowance',
|
|
202
|
+
templateId: 'todos-app' as TemplateId,
|
|
203
|
+
title: 'Chores & Allowance',
|
|
204
|
+
description:
|
|
205
|
+
'Family task management with approval workflows. Teach financial accountability safely.',
|
|
206
|
+
tags: ['Family', 'Ops'],
|
|
207
|
+
capabilities: 'Tasks, Approvals, Notifications',
|
|
208
|
+
previewUrl: '/sandbox?template=chores-allowance',
|
|
209
|
+
docsUrl: '/docs/specs/workflows',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
id: 'service-dispatch',
|
|
213
|
+
templateId: 'messaging-app' as TemplateId,
|
|
214
|
+
title: 'Service Dispatch',
|
|
215
|
+
description:
|
|
216
|
+
'Field service scheduling, routing, and invoicing. Real-time coordination with policy gates.',
|
|
217
|
+
tags: ['Ops', 'Trades'],
|
|
218
|
+
capabilities: 'Scheduling, Maps, Invoicing',
|
|
219
|
+
previewUrl: '/sandbox?template=service-dispatch',
|
|
220
|
+
docsUrl: '/docs/specs/workflows',
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'content-review',
|
|
224
|
+
templateId: 'todos-app' as TemplateId,
|
|
225
|
+
title: 'Content Review',
|
|
226
|
+
description:
|
|
227
|
+
'Multi-stage approval workflow for content. Audit trail for every decision.',
|
|
228
|
+
tags: ['Ops'],
|
|
229
|
+
capabilities: 'Workflows, Approvals, Comments',
|
|
230
|
+
previewUrl: '/sandbox?template=content-review',
|
|
231
|
+
docsUrl: '/docs/specs/workflows',
|
|
232
|
+
},
|
|
233
233
|
];
|
|
234
234
|
type LocalTemplate = (typeof templates)[number];
|
|
235
235
|
|
|
236
236
|
const allTags = [
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
'Getting Started',
|
|
238
|
+
'SaaS',
|
|
239
|
+
'Business',
|
|
240
|
+
'CRM',
|
|
241
|
+
'AI',
|
|
242
|
+
'Trades',
|
|
243
|
+
'Coliving',
|
|
244
|
+
'Family',
|
|
245
|
+
'Ops',
|
|
246
|
+
'Payments',
|
|
247
|
+
'Learning',
|
|
248
|
+
'Platform',
|
|
249
249
|
];
|
|
250
250
|
|
|
251
251
|
export const TemplatesPage = () => {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
const [selectedTag, setSelectedTag] = useState<string | null>(null);
|
|
253
|
+
const [search, setSearch] = useState('');
|
|
254
|
+
const [preview, setPreview] = useState<TemplateId | null>(null);
|
|
255
|
+
const [studioSignupModalOpen, setStudioSignupModalOpen] = useState(false);
|
|
256
|
+
const [source, setSource] = useState<'local' | 'registry'>('local');
|
|
257
|
+
const [selectedTemplateForCommand, setSelectedTemplateForCommand] = useState<
|
|
258
|
+
RegistryTemplate | LocalTemplate | null
|
|
259
|
+
>(null);
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
const { data: registryTemplates = [], isLoading: registryLoading } =
|
|
262
|
+
useRegistryTemplates();
|
|
263
263
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
264
|
+
const filtered = templates.filter((t) => {
|
|
265
|
+
const matchTag = !selectedTag || t.tags.includes(selectedTag);
|
|
266
|
+
const matchSearch =
|
|
267
|
+
!search ||
|
|
268
|
+
t.title.toLowerCase().includes(search.toLowerCase()) ||
|
|
269
|
+
t.description.toLowerCase().includes(search.toLowerCase());
|
|
270
|
+
return matchTag && matchSearch;
|
|
271
|
+
});
|
|
272
272
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
const commandId = selectedTemplateForCommand
|
|
274
|
+
? 'templateId' in selectedTemplateForCommand
|
|
275
|
+
? selectedTemplateForCommand.templateId
|
|
276
|
+
: selectedTemplateForCommand.id
|
|
277
|
+
: '';
|
|
278
278
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
279
|
+
return (
|
|
280
|
+
<TooltipProvider>
|
|
281
|
+
<main>
|
|
282
|
+
<section className="section-padding hero-gradient border-border/70 border-b">
|
|
283
|
+
<div className="editorial-shell space-y-8">
|
|
284
|
+
<div className="max-w-4xl space-y-5">
|
|
285
|
+
<p className="editorial-kicker">Proof through real scenarios</p>
|
|
286
|
+
<h1 className="editorial-title">
|
|
287
|
+
Templates that show the open system in practice.
|
|
288
|
+
</h1>
|
|
289
|
+
<p className="editorial-subtitle">
|
|
290
|
+
These scenarios are the fastest way to understand ContractSpec:
|
|
291
|
+
explicit contracts, aligned surfaces, and an adoption path from
|
|
292
|
+
OSS exploration into Studio deployment.
|
|
293
|
+
</p>
|
|
294
|
+
</div>
|
|
295
|
+
<div className="editorial-proof-strip">
|
|
296
|
+
<div className="editorial-stat">
|
|
297
|
+
<span className="editorial-stat-value">{templates.length}</span>
|
|
298
|
+
<span className="editorial-label">curated scenarios</span>
|
|
299
|
+
</div>
|
|
300
|
+
<div className="editorial-stat">
|
|
301
|
+
<span className="editorial-stat-value">2</span>
|
|
302
|
+
<span className="editorial-label">entry paths</span>
|
|
303
|
+
</div>
|
|
304
|
+
<div className="editorial-stat">
|
|
305
|
+
<span className="editorial-stat-value">OSS</span>
|
|
306
|
+
<span className="editorial-label">first, Studio second</span>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</section>
|
|
294
311
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
312
|
+
<section className="editorial-section">
|
|
313
|
+
<div className="editorial-shell space-y-6">
|
|
314
|
+
<div className="flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
|
|
315
|
+
<div className="max-w-3xl space-y-3">
|
|
316
|
+
<p className="editorial-kicker">Browse by source</p>
|
|
317
|
+
<h2 className="font-serif text-4xl tracking-[-0.04em]">
|
|
318
|
+
Use local scenarios for core proof, then scan the community.
|
|
319
|
+
</h2>
|
|
320
|
+
<p className="text-muted-foreground text-sm leading-7">
|
|
321
|
+
Local templates show the official adoption path. Community
|
|
322
|
+
templates show where the ecosystem is pushing the system next.
|
|
323
|
+
</p>
|
|
324
|
+
</div>
|
|
325
|
+
<div className="flex gap-2">
|
|
326
|
+
<button
|
|
327
|
+
onClick={() => setSource('local')}
|
|
328
|
+
className={cn(
|
|
329
|
+
'rounded-full px-4 py-2 font-medium text-sm transition-colors',
|
|
330
|
+
{
|
|
331
|
+
'bg-primary text-primary-foreground': source === 'local',
|
|
332
|
+
'border border-border bg-card hover:bg-card/80':
|
|
333
|
+
source !== 'local',
|
|
334
|
+
}
|
|
335
|
+
)}
|
|
336
|
+
aria-pressed={source === 'local'}
|
|
337
|
+
>
|
|
338
|
+
Local
|
|
339
|
+
</button>
|
|
340
|
+
<button
|
|
341
|
+
onClick={() => setSource('registry')}
|
|
342
|
+
className={cn(
|
|
343
|
+
'rounded-full px-4 py-2 font-medium text-sm transition-colors',
|
|
344
|
+
{
|
|
345
|
+
'bg-primary text-primary-foreground':
|
|
346
|
+
source === 'registry',
|
|
347
|
+
'border border-border bg-card hover:bg-card/80':
|
|
348
|
+
source !== 'registry',
|
|
349
|
+
}
|
|
350
|
+
)}
|
|
351
|
+
aria-pressed={source === 'registry'}
|
|
352
|
+
>
|
|
353
|
+
Community
|
|
354
|
+
</button>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
<div className="editorial-panel space-y-5">
|
|
358
|
+
<div className="relative">
|
|
359
|
+
<Search
|
|
360
|
+
className="absolute top-3.5 left-4 text-muted-foreground"
|
|
361
|
+
size={18}
|
|
362
|
+
/>
|
|
363
|
+
<input
|
|
364
|
+
type="text"
|
|
365
|
+
placeholder="Search scenarios, industries, or capabilities"
|
|
366
|
+
value={search}
|
|
367
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
368
|
+
className="w-full rounded-full border border-border bg-background px-12 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
|
369
|
+
aria-label="Search templates"
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
<div className="flex flex-wrap gap-2">
|
|
373
|
+
<button
|
|
374
|
+
onClick={() => setSelectedTag(null)}
|
|
375
|
+
className={cn(
|
|
376
|
+
'rounded-full px-4 py-2 font-medium text-sm transition-colors',
|
|
377
|
+
{
|
|
378
|
+
'bg-primary text-primary-foreground':
|
|
379
|
+
selectedTag === null,
|
|
380
|
+
'border border-border bg-card hover:bg-card/80':
|
|
381
|
+
selectedTag !== null,
|
|
382
|
+
}
|
|
383
|
+
)}
|
|
384
|
+
aria-pressed={selectedTag === null}
|
|
385
|
+
>
|
|
386
|
+
All
|
|
387
|
+
</button>
|
|
388
|
+
{allTags.map((tag) => (
|
|
389
|
+
<button
|
|
390
|
+
key={tag}
|
|
391
|
+
onClick={() => setSelectedTag(tag)}
|
|
392
|
+
className={cn(
|
|
393
|
+
'rounded-full px-4 py-2 font-medium text-sm transition-colors',
|
|
394
|
+
{
|
|
395
|
+
'bg-primary text-primary-foreground':
|
|
396
|
+
selectedTag === tag,
|
|
397
|
+
'border border-border bg-card hover:bg-card/80':
|
|
398
|
+
selectedTag !== tag,
|
|
399
|
+
}
|
|
400
|
+
)}
|
|
401
|
+
aria-pressed={selectedTag === tag}
|
|
402
|
+
>
|
|
403
|
+
{tag}
|
|
404
|
+
</button>
|
|
405
|
+
))}
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</section>
|
|
377
410
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
411
|
+
<section className="section-padding">
|
|
412
|
+
<div className="editorial-shell">
|
|
413
|
+
{source === 'registry' ? (
|
|
414
|
+
registryLoading ? (
|
|
415
|
+
<div className="py-12 text-center">
|
|
416
|
+
<p className="text-muted-foreground">
|
|
417
|
+
Loading community templates…
|
|
418
|
+
</p>
|
|
419
|
+
</div>
|
|
420
|
+
) : registryTemplates.length === 0 ? (
|
|
421
|
+
<div className="py-12 text-center">
|
|
422
|
+
<p className="text-muted-foreground">
|
|
423
|
+
No community templates found (configure
|
|
424
|
+
`NEXT_PUBLIC_CONTRACTSPEC_REGISTRY_URL`).
|
|
425
|
+
</p>
|
|
426
|
+
</div>
|
|
427
|
+
) : (
|
|
428
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
429
|
+
{registryTemplates.map((t) => (
|
|
430
|
+
<div
|
|
431
|
+
key={t.id}
|
|
432
|
+
className="editorial-panel relative flex flex-col space-y-4 transition-colors hover:border-[color:rgb(162_79_42_/_0.55)]"
|
|
433
|
+
>
|
|
434
|
+
<div>
|
|
435
|
+
<h3 className="font-serif text-2xl tracking-[-0.03em]">
|
|
436
|
+
{t.name}
|
|
437
|
+
</h3>
|
|
438
|
+
<p className="mt-1 text-muted-foreground text-sm">
|
|
439
|
+
{t.description}
|
|
440
|
+
</p>
|
|
441
|
+
</div>
|
|
442
|
+
<div className="flex-1 space-y-2">
|
|
443
|
+
<div className="flex flex-wrap gap-1">
|
|
444
|
+
{t.tags.map((tag) => (
|
|
445
|
+
<span
|
|
446
|
+
key={tag}
|
|
447
|
+
className="rounded-full border border-border bg-muted px-3 py-1 text-[11px] text-muted-foreground"
|
|
448
|
+
>
|
|
449
|
+
{tag}
|
|
450
|
+
</span>
|
|
451
|
+
))}
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
<div className="flex gap-2 pt-4">
|
|
455
|
+
<Tooltip>
|
|
456
|
+
<TooltipTrigger asChild>
|
|
457
|
+
<button
|
|
458
|
+
className="btn-ghost flex-1 text-center text-xs"
|
|
459
|
+
onClick={() => {
|
|
460
|
+
const local = getTemplate(t.id as TemplateId);
|
|
461
|
+
if (!local) {
|
|
462
|
+
setSelectedTemplateForCommand(t);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
setPreview(t.id as TemplateId);
|
|
466
|
+
}}
|
|
467
|
+
>
|
|
468
|
+
Preview
|
|
469
|
+
</button>
|
|
470
|
+
</TooltipTrigger>
|
|
471
|
+
<TooltipContent>
|
|
472
|
+
<p>Preview this template (if available locally)</p>
|
|
473
|
+
</TooltipContent>
|
|
474
|
+
</Tooltip>
|
|
475
|
+
<Tooltip>
|
|
476
|
+
<TooltipTrigger asChild>
|
|
477
|
+
<button
|
|
478
|
+
className="btn-primary flex-1 text-center text-xs"
|
|
479
|
+
onClick={() => {
|
|
480
|
+
captureAnalyticsEvent(
|
|
481
|
+
analyticsEventNames.EXAMPLE_REPO_OPEN,
|
|
482
|
+
{
|
|
483
|
+
surface: 'templates',
|
|
484
|
+
templateId: t.id,
|
|
485
|
+
source: 'registry',
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
setSelectedTemplateForCommand(t);
|
|
489
|
+
}}
|
|
490
|
+
>
|
|
491
|
+
Use Template
|
|
492
|
+
</button>
|
|
493
|
+
</TooltipTrigger>
|
|
494
|
+
<TooltipContent>
|
|
495
|
+
<p>Get CLI command</p>
|
|
496
|
+
</TooltipContent>
|
|
497
|
+
</Tooltip>
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
500
|
+
))}
|
|
501
|
+
</div>
|
|
502
|
+
)
|
|
503
|
+
) : filtered.length === 0 ? (
|
|
504
|
+
<div className="py-12 text-center">
|
|
505
|
+
<p className="text-muted-foreground">
|
|
506
|
+
No templates match your filters. Try a different search.
|
|
507
|
+
</p>
|
|
508
|
+
</div>
|
|
509
|
+
) : (
|
|
510
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
511
|
+
{filtered.map((template, i) => (
|
|
512
|
+
<div
|
|
513
|
+
key={i}
|
|
514
|
+
className="editorial-panel relative flex flex-col space-y-4 transition-colors hover:border-[color:rgb(162_79_42_/_0.55)]"
|
|
515
|
+
>
|
|
516
|
+
{'isNew' in template && template.isNew && (
|
|
517
|
+
<span className="absolute top-4 right-4 rounded-full bg-[color:var(--success)] px-2.5 py-1 font-medium text-[11px] text-white uppercase">
|
|
518
|
+
New
|
|
519
|
+
</span>
|
|
520
|
+
)}
|
|
521
|
+
<div>
|
|
522
|
+
<h3 className="font-serif text-2xl tracking-[-0.03em]">
|
|
523
|
+
{template.title}
|
|
524
|
+
</h3>
|
|
525
|
+
<p className="mt-1 text-muted-foreground text-sm">
|
|
526
|
+
{template.description}
|
|
527
|
+
</p>
|
|
528
|
+
</div>
|
|
529
|
+
<div className="flex-1 space-y-2">
|
|
530
|
+
<p className="text-muted-foreground text-xs">
|
|
531
|
+
<span className="font-medium text-foreground">
|
|
532
|
+
Capabilities:
|
|
533
|
+
</span>{' '}
|
|
534
|
+
{template.capabilities}
|
|
535
|
+
</p>
|
|
536
|
+
<div className="flex flex-wrap gap-1">
|
|
537
|
+
{template.tags.map((tag) => (
|
|
538
|
+
<span
|
|
539
|
+
key={tag}
|
|
540
|
+
className="rounded-full border border-border bg-muted px-3 py-1 text-[11px] text-muted-foreground"
|
|
541
|
+
>
|
|
542
|
+
{tag}
|
|
543
|
+
</span>
|
|
544
|
+
))}
|
|
545
|
+
</div>
|
|
546
|
+
</div>
|
|
547
|
+
<div className="flex gap-2 pt-4">
|
|
548
|
+
<Tooltip>
|
|
549
|
+
<TooltipTrigger asChild>
|
|
550
|
+
<button
|
|
551
|
+
className="btn-ghost flex-1 text-center text-xs"
|
|
552
|
+
onClick={() => setPreview(template.templateId)}
|
|
553
|
+
>
|
|
554
|
+
Preview
|
|
555
|
+
</button>
|
|
556
|
+
</TooltipTrigger>
|
|
557
|
+
<TooltipContent>
|
|
558
|
+
<p>Preview this template in a modal</p>
|
|
559
|
+
</TooltipContent>
|
|
560
|
+
</Tooltip>
|
|
561
|
+
<Tooltip>
|
|
562
|
+
<TooltipTrigger asChild>
|
|
563
|
+
<button
|
|
564
|
+
className="btn-primary flex-1 text-center text-xs"
|
|
565
|
+
onClick={() => {
|
|
566
|
+
captureAnalyticsEvent(
|
|
567
|
+
analyticsEventNames.EXAMPLE_REPO_OPEN,
|
|
568
|
+
{
|
|
569
|
+
surface: 'templates',
|
|
570
|
+
templateId: template.templateId,
|
|
571
|
+
source: 'local',
|
|
572
|
+
}
|
|
573
|
+
);
|
|
574
|
+
setSelectedTemplateForCommand(template);
|
|
575
|
+
}}
|
|
576
|
+
>
|
|
577
|
+
Use Template
|
|
578
|
+
</button>
|
|
579
|
+
</TooltipTrigger>
|
|
580
|
+
<TooltipContent>
|
|
581
|
+
<p>Get CLI command</p>
|
|
582
|
+
</TooltipContent>
|
|
583
|
+
</Tooltip>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
))}
|
|
587
|
+
</div>
|
|
588
|
+
)}
|
|
589
|
+
</div>
|
|
590
|
+
</section>
|
|
555
591
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
592
|
+
<section className="editorial-section bg-striped">
|
|
593
|
+
<div className="editorial-shell space-y-8">
|
|
594
|
+
<div className="max-w-3xl space-y-4">
|
|
595
|
+
<p className="editorial-kicker">From template to real system</p>
|
|
596
|
+
<h2 className="font-serif text-4xl tracking-[-0.04em] md:text-5xl">
|
|
597
|
+
Templates become useful when the system can absorb more context.
|
|
598
|
+
</h2>
|
|
599
|
+
<p className="editorial-copy">
|
|
600
|
+
Use templates to prove the base flow, then layer integrations,
|
|
601
|
+
knowledge, and runtime behavior on top without losing the same
|
|
602
|
+
contract source.
|
|
603
|
+
</p>
|
|
604
|
+
</div>
|
|
605
|
+
<div className="grid gap-6 md:grid-cols-3">
|
|
606
|
+
<div className="editorial-panel space-y-4">
|
|
607
|
+
<div className="text-3xl">💳</div>
|
|
608
|
+
<h3 className="font-serif text-2xl tracking-[-0.03em]">
|
|
609
|
+
Add payments
|
|
610
|
+
</h3>
|
|
611
|
+
<p className="text-muted-foreground text-sm">
|
|
612
|
+
Connect Stripe to any template for payment processing,
|
|
613
|
+
subscriptions, and invoicing. Type-safe and policy-enforced.
|
|
614
|
+
</p>
|
|
615
|
+
<Link
|
|
616
|
+
href="/docs/integrations/stripe"
|
|
617
|
+
className="font-medium text-[color:var(--blue)] text-sm hover:opacity-80"
|
|
618
|
+
>
|
|
619
|
+
Learn more →
|
|
620
|
+
</Link>
|
|
621
|
+
</div>
|
|
622
|
+
<div className="editorial-panel space-y-4">
|
|
623
|
+
<div className="text-3xl">📧</div>
|
|
624
|
+
<h3 className="font-serif text-2xl tracking-[-0.03em]">
|
|
625
|
+
Add notifications
|
|
626
|
+
</h3>
|
|
627
|
+
<p className="text-muted-foreground text-sm">
|
|
628
|
+
Send transactional emails via Postmark or Resend. Process
|
|
629
|
+
inbound emails with Gmail API. SMS via Twilio.
|
|
630
|
+
</p>
|
|
631
|
+
<Link
|
|
632
|
+
href="/docs/integrations"
|
|
633
|
+
className="font-medium text-[color:var(--blue)] text-sm hover:opacity-80"
|
|
634
|
+
>
|
|
635
|
+
View integrations →
|
|
636
|
+
</Link>
|
|
637
|
+
</div>
|
|
638
|
+
<div className="editorial-panel space-y-4">
|
|
639
|
+
<div className="text-3xl">🧠</div>
|
|
640
|
+
<h3 className="font-serif text-2xl tracking-[-0.03em]">
|
|
641
|
+
Add AI and knowledge
|
|
642
|
+
</h3>
|
|
643
|
+
<p className="text-muted-foreground text-sm">
|
|
644
|
+
Power templates with OpenAI, vector search via Qdrant, and
|
|
645
|
+
structured knowledge spaces for context-aware workflows.
|
|
646
|
+
</p>
|
|
647
|
+
<Link
|
|
648
|
+
href="/docs/knowledge"
|
|
649
|
+
className="font-medium text-[color:var(--blue)] text-sm hover:opacity-80"
|
|
650
|
+
>
|
|
651
|
+
Learn about knowledge →
|
|
652
|
+
</Link>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
<div className="pt-4 text-center">
|
|
656
|
+
<p className="mb-4 text-muted-foreground text-sm">
|
|
657
|
+
All integrations are configured per-tenant with automatic health
|
|
658
|
+
checks and credential rotation.
|
|
659
|
+
</p>
|
|
660
|
+
<Link href="/docs/architecture" className="btn-primary">
|
|
661
|
+
View Architecture
|
|
662
|
+
</Link>
|
|
663
|
+
</div>
|
|
664
|
+
</div>
|
|
665
|
+
</section>
|
|
666
|
+
</main>
|
|
625
667
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
668
|
+
{/*{preview ? (*/}
|
|
669
|
+
<TemplatePreviewModal
|
|
670
|
+
templateId={preview}
|
|
671
|
+
onClose={() => {
|
|
672
|
+
setPreview(null);
|
|
673
|
+
}}
|
|
674
|
+
/>
|
|
675
|
+
{/*) : null}*/}
|
|
634
676
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
677
|
+
<Dialog
|
|
678
|
+
open={studioSignupModalOpen}
|
|
679
|
+
onOpenChange={setStudioSignupModalOpen}
|
|
680
|
+
>
|
|
681
|
+
<DialogContent className="max-h-[90vh] max-w-2xl overflow-y-auto">
|
|
682
|
+
<DialogHeader>
|
|
683
|
+
<DialogTitle>Deploy in Studio</DialogTitle>
|
|
684
|
+
<DialogDescription>
|
|
685
|
+
Deploy templates in ContractSpec Studio and run the full
|
|
686
|
+
evidence-to-spec loop with your team.
|
|
687
|
+
</DialogDescription>
|
|
688
|
+
</DialogHeader>
|
|
689
|
+
<StudioSignupSection variant="compact" />
|
|
690
|
+
</DialogContent>
|
|
691
|
+
</Dialog>
|
|
650
692
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
693
|
+
<Dialog
|
|
694
|
+
open={!!selectedTemplateForCommand}
|
|
695
|
+
onOpenChange={() => setSelectedTemplateForCommand(null)}
|
|
696
|
+
>
|
|
697
|
+
<DialogContent className="max-w-md">
|
|
698
|
+
<DialogHeader>
|
|
699
|
+
<DialogTitle>Use this template</DialogTitle>
|
|
700
|
+
<DialogDescription>
|
|
701
|
+
Initialize a new project with this template using the CLI.
|
|
702
|
+
</DialogDescription>
|
|
703
|
+
</DialogHeader>
|
|
704
|
+
<div className="space-y-4 pt-4">
|
|
705
|
+
<div className="rounded-md border border-zinc-800 bg-zinc-950 p-4 font-mono text-sm text-zinc-50">
|
|
706
|
+
npx contractspec init --template {commandId}
|
|
707
|
+
</div>
|
|
708
|
+
<div className="flex gap-2">
|
|
709
|
+
<button
|
|
710
|
+
className="btn-secondary w-full"
|
|
711
|
+
onClick={() => {
|
|
712
|
+
navigator.clipboard.writeText(
|
|
713
|
+
`npx contractspec init --template ${commandId}`
|
|
714
|
+
);
|
|
715
|
+
captureAnalyticsEvent(
|
|
716
|
+
analyticsEventNames.COPY_COMMAND_CLICK,
|
|
717
|
+
{
|
|
718
|
+
surface: 'templates',
|
|
719
|
+
templateId: commandId,
|
|
720
|
+
filename: 'templates-cli',
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
}}
|
|
724
|
+
>
|
|
725
|
+
Copy Command
|
|
726
|
+
</button>
|
|
727
|
+
</div>
|
|
728
|
+
<div className="relative">
|
|
729
|
+
<div className="absolute inset-0 flex items-center">
|
|
730
|
+
<span className="w-full border-border border-t" />
|
|
731
|
+
</div>
|
|
732
|
+
<div className="relative flex justify-center text-xs uppercase">
|
|
733
|
+
<span className="bg-background px-2 text-muted-foreground">
|
|
734
|
+
Or
|
|
735
|
+
</span>
|
|
736
|
+
</div>
|
|
737
|
+
</div>
|
|
738
|
+
<button
|
|
739
|
+
className="btn-ghost w-full text-sm"
|
|
740
|
+
onClick={() => {
|
|
741
|
+
captureAnalyticsEvent(analyticsEventNames.CTA_STUDIO_CLICK, {
|
|
742
|
+
surface: 'templates',
|
|
743
|
+
templateId: commandId,
|
|
744
|
+
});
|
|
745
|
+
setSelectedTemplateForCommand(null);
|
|
746
|
+
setStudioSignupModalOpen(true);
|
|
747
|
+
}}
|
|
748
|
+
>
|
|
749
|
+
Deploy to Studio
|
|
750
|
+
</button>
|
|
751
|
+
</div>
|
|
752
|
+
</DialogContent>
|
|
753
|
+
</Dialog>
|
|
754
|
+
</TooltipProvider>
|
|
755
|
+
);
|
|
714
756
|
};
|