@donotdev/cli 0.0.18 → 0.0.20

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 (150) hide show
  1. package/dependencies-matrix.json +42 -55
  2. package/dist/bin/commands/bump.js +5 -2
  3. package/dist/bin/commands/coach.js +8177 -0
  4. package/dist/bin/commands/create-app.js +6 -6
  5. package/dist/bin/commands/create-project.js +23 -9
  6. package/dist/bin/commands/deploy.js +99 -59
  7. package/dist/bin/commands/doctor.js +243 -698
  8. package/dist/bin/commands/emu.js +2 -2
  9. package/dist/bin/commands/format.js +4 -1
  10. package/dist/bin/commands/get-demo.js +8351 -0
  11. package/dist/bin/commands/make-admin.js +773 -152
  12. package/dist/bin/commands/setup.js +524 -1713
  13. package/dist/bin/commands/staging.js +17870 -0
  14. package/dist/bin/commands/sync-secrets.js +2 -11
  15. package/dist/bin/commands/type-check.js +7738 -1712
  16. package/dist/bin/dndev.js +868 -199
  17. package/dist/bin/donotdev.js +868 -199
  18. package/dist/index.js +127 -67
  19. package/package.json +1 -1
  20. package/templates/app-demo/index.html.example +147 -10
  21. package/templates/app-demo/public/apple-touch-icon.png.example +0 -0
  22. package/templates/app-demo/public/favicon.svg.example +1 -0
  23. package/templates/app-demo/public/icon-192x192.png.example +0 -0
  24. package/templates/app-demo/public/icon-512x512.png.example +0 -0
  25. package/templates/app-demo/src/App.tsx.example +7 -11
  26. package/templates/app-demo/src/config/app.ts.example +13 -48
  27. package/templates/app-demo/src/entities/booking.ts.example +75 -0
  28. package/templates/app-demo/src/entities/onboarding.ts.example +160 -0
  29. package/templates/app-demo/src/entities/product.ts.example +50 -0
  30. package/templates/app-demo/src/entities/quote.ts.example +70 -0
  31. package/templates/app-demo/src/globals.css.example +5 -1
  32. package/templates/app-demo/src/main.tsx.example +13 -7
  33. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +41 -0
  34. package/templates/app-demo/src/pages/ConditionalFormPage.tsx.example +88 -0
  35. package/templates/app-demo/src/pages/DashboardPage.tsx.example +17 -0
  36. package/templates/app-demo/src/pages/HomePage.tsx.example +339 -60
  37. package/templates/app-demo/src/pages/OnboardingPage.tsx.example +47 -0
  38. package/templates/app-demo/src/pages/PricingPage.tsx.example +41 -0
  39. package/templates/app-demo/src/pages/ProductsPage.tsx.example +19 -0
  40. package/templates/app-demo/src/pages/ProfilePage.tsx.example +18 -0
  41. package/templates/app-demo/src/pages/SettingsPage.tsx.example +17 -0
  42. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +118 -0
  43. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +93 -0
  44. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +147 -51
  45. package/templates/app-demo/src/pages/components/ComponentsData.tsx.example +103 -21
  46. package/templates/app-demo/src/pages/components/componentConfig.ts.example +139 -59
  47. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +25 -0
  48. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +23 -0
  49. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +23 -0
  50. package/templates/app-demo/src/themes.css.example +289 -77
  51. package/templates/app-demo/stats.html.example +4949 -0
  52. package/templates/app-demo/tsconfig.json.example +1 -1
  53. package/templates/app-demo/vite.config.ts.example +23 -48
  54. package/templates/app-expo/README.md.example +1 -1
  55. package/templates/app-expo/app/index.tsx.example +1 -1
  56. package/templates/app-next/src/locales/home_en.json.example +6 -6
  57. package/templates/app-vite/src/locales/home_en.json.example +6 -6
  58. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  59. package/templates/overlay-firebase/env.fragment.example +1 -1
  60. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  61. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  62. package/templates/overlay-supabase/env.fragment.example +1 -1
  63. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  64. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  65. package/templates/overlay-vercel/env.fragment.example +1 -1
  66. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  67. package/templates/root-consumer/AI.md.example +4 -3
  68. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  69. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  70. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  71. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  72. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  73. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  74. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  75. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  76. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  77. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  78. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  79. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
  80. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  81. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  82. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  83. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  84. package/templates/root-consumer/guides/dndev/advanced/COOKIE_REFERENCE.md.example +252 -252
  85. package/templates/root-consumer/guides/dndev/advanced/VERSION_CONTROL.md.example +174 -174
  86. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  87. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  88. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  89. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  90. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  91. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  92. package/dist/bin/commands/agent-setup.d.ts +0 -6
  93. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  94. package/dist/bin/commands/agent-setup.js.map +0 -1
  95. package/dist/bin/commands/build.d.ts +0 -11
  96. package/dist/bin/commands/build.d.ts.map +0 -1
  97. package/dist/bin/commands/build.js.map +0 -1
  98. package/dist/bin/commands/bump.d.ts +0 -11
  99. package/dist/bin/commands/bump.d.ts.map +0 -1
  100. package/dist/bin/commands/bump.js.map +0 -1
  101. package/dist/bin/commands/cacheout.d.ts +0 -11
  102. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  103. package/dist/bin/commands/cacheout.js.map +0 -1
  104. package/dist/bin/commands/create-app.d.ts +0 -11
  105. package/dist/bin/commands/create-app.d.ts.map +0 -1
  106. package/dist/bin/commands/create-app.js.map +0 -1
  107. package/dist/bin/commands/create-project.d.ts +0 -11
  108. package/dist/bin/commands/create-project.d.ts.map +0 -1
  109. package/dist/bin/commands/create-project.js.map +0 -1
  110. package/dist/bin/commands/deploy.d.ts +0 -11
  111. package/dist/bin/commands/deploy.d.ts.map +0 -1
  112. package/dist/bin/commands/deploy.js.map +0 -1
  113. package/dist/bin/commands/dev.d.ts +0 -11
  114. package/dist/bin/commands/dev.d.ts.map +0 -1
  115. package/dist/bin/commands/dev.js.map +0 -1
  116. package/dist/bin/commands/doctor.d.ts +0 -6
  117. package/dist/bin/commands/doctor.d.ts.map +0 -1
  118. package/dist/bin/commands/doctor.js.map +0 -1
  119. package/dist/bin/commands/emu.d.ts +0 -11
  120. package/dist/bin/commands/emu.d.ts.map +0 -1
  121. package/dist/bin/commands/emu.js.map +0 -1
  122. package/dist/bin/commands/format.d.ts +0 -11
  123. package/dist/bin/commands/format.d.ts.map +0 -1
  124. package/dist/bin/commands/format.js.map +0 -1
  125. package/dist/bin/commands/make-admin.d.ts +0 -11
  126. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  127. package/dist/bin/commands/make-admin.js.map +0 -1
  128. package/dist/bin/commands/preview.d.ts +0 -11
  129. package/dist/bin/commands/preview.d.ts.map +0 -1
  130. package/dist/bin/commands/preview.js.map +0 -1
  131. package/dist/bin/commands/setup.d.ts +0 -6
  132. package/dist/bin/commands/setup.d.ts.map +0 -1
  133. package/dist/bin/commands/setup.js.map +0 -1
  134. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  135. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  136. package/dist/bin/commands/sync-secrets.js.map +0 -1
  137. package/dist/bin/commands/type-check.d.ts +0 -14
  138. package/dist/bin/commands/type-check.d.ts.map +0 -1
  139. package/dist/bin/commands/type-check.js.map +0 -1
  140. package/dist/bin/commands/wai.d.ts +0 -11
  141. package/dist/bin/commands/wai.d.ts.map +0 -1
  142. package/dist/bin/commands/wai.js.map +0 -1
  143. package/dist/index.d.ts +0 -8
  144. package/dist/index.d.ts.map +0 -1
  145. package/dist/index.js.map +0 -1
  146. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  147. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  148. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  149. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  150. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
@@ -1,79 +1,358 @@
1
+ 'use client';
1
2
  // apps/demo/src/pages/HomePage.tsx
2
3
 
3
- import { useMemo } from 'react';
4
- import { useNavigate, useOutletContext } from 'react-router-dom';
4
+ import {
5
+ Zap,
6
+ Shield,
7
+ Rocket,
8
+ UserPlus,
9
+ Settings,
10
+ Play,
11
+ Quote,
12
+ } from 'lucide-react';
5
13
 
6
14
  import {
7
15
  Badge,
16
+ BADGE_VARIANT,
17
+ Button,
18
+ BUTTON_VARIANT,
19
+ CallToAction,
8
20
  Card,
9
- Grid,
21
+ CARD_VARIANT,
22
+ Carousel,
23
+ HeroSection,
24
+ Marquee,
25
+ Roadmap,
10
26
  Section,
27
+ SplitReveal,
11
28
  Stack,
29
+ Text,
12
30
  } from '@donotdev/components';
31
+ import { useTranslation } from '@donotdev/core';
32
+ import { FeatureCard, PageContainer } from '@donotdev/ui';
13
33
 
14
- import {
15
- COMPONENT_CONFIGS,
16
- getCSSFamilies,
17
- } from './components/componentConfig';
18
- import type { CSSFamily } from './components/ComponentsData';
34
+ import type { RoadmapStep } from '@donotdev/components';
19
35
 
20
- type LayoutContext = {
21
- selectedTab: CSSFamily | 'all';
22
- searchQuery: string;
23
- };
36
+ // -- Fake testimonials for Marquee showcase --
37
+ const testimonials = [
38
+ {
39
+ name: 'Sarah K.',
40
+ role: 'CTO @ Fintech',
41
+ text: 'Shipped our MVP in 3 weeks. CRUD, auth, billing — all wired.',
42
+ },
43
+ {
44
+ name: 'Marco R.',
45
+ role: 'Solo Founder',
46
+ text: 'I replaced 6 libraries with one framework. No regrets.',
47
+ },
48
+ {
49
+ name: 'Priya N.',
50
+ role: 'Lead Dev',
51
+ text: 'The type safety alone saved us from 2 production bugs on day one.',
52
+ },
53
+ {
54
+ name: 'James L.',
55
+ role: 'Agency Owner',
56
+ text: 'We spin up client projects in hours now, not weeks.',
57
+ },
58
+ {
59
+ name: 'Yuki T.',
60
+ role: 'Indie Hacker',
61
+ text: 'Dark mode, RTL, i18n — all free. I just write features.',
62
+ },
63
+ {
64
+ name: 'Elena M.',
65
+ role: 'Staff Engineer',
66
+ text: 'Best DX I have seen in a React meta-framework. Period.',
67
+ },
68
+ {
69
+ name: 'David C.',
70
+ role: 'Freelancer',
71
+ text: 'Entity definitions + auto CRUD cut my project setup time by 80%.',
72
+ },
73
+ {
74
+ name: 'Lisa W.',
75
+ role: 'Tech Lead',
76
+ text: 'Finally a framework where the components actually respect the theme system.',
77
+ },
78
+ {
79
+ name: 'Tom H.',
80
+ role: 'Product Engineer',
81
+ text: 'Billing integration took 20 minutes. Stripe webhooks just work.',
82
+ },
83
+ {
84
+ name: 'Aisha B.',
85
+ role: 'Startup CTO',
86
+ text: 'We went from zero to production in 2 weeks. Not a joke.',
87
+ },
88
+ ];
24
89
 
25
- export default function HomePage() {
26
- const navigate = useNavigate();
27
- const {
28
- selectedTab,
29
- searchQuery,
30
- } = useOutletContext<LayoutContext>();
90
+ // -- Carousel items: showcase different component types --
91
+ const showcaseItems = [
92
+ {
93
+ title: 'Reveal Animations',
94
+ description:
95
+ 'Staggered, directional entrance animations with viewport detection.',
96
+ variant: CARD_VARIANT.ACCENT,
97
+ icon: Zap,
98
+ },
99
+ {
100
+ title: 'Smart Forms',
101
+ description:
102
+ 'Conditional fields, draft validation, multi-step wizards — all from entity definitions.',
103
+ variant: CARD_VARIANT.DEFAULT,
104
+ icon: Settings,
105
+ },
106
+ {
107
+ title: 'Carousel & Marquee',
108
+ description:
109
+ 'Autoplay, swipe, infinite loop, momentum physics. This very section.',
110
+ variant: CARD_VARIANT.DEFAULT,
111
+ icon: Play,
112
+ },
113
+ {
114
+ title: 'Theme System',
115
+ description:
116
+ '5 themes with full design token coverage. Switch live, no flash.',
117
+ variant: CARD_VARIANT.DEFAULT,
118
+ icon: Shield,
119
+ },
120
+ {
121
+ title: 'StackedCards & Bento',
122
+ description:
123
+ 'Scroll-reveal stacked layouts and asymmetric grids for landing pages.',
124
+ variant: CARD_VARIANT.DEFAULT,
125
+ icon: Rocket,
126
+ },
127
+ ];
31
128
 
32
- const componentsInTab = useMemo(() => {
33
- return COMPONENT_CONFIGS.filter((config) => {
34
- if (selectedTab !== 'all' && config.cssFamily !== selectedTab)
35
- return false;
129
+ export default function HomePage() {
130
+ const { t } = useTranslation('dndev');
36
131
 
37
- const matchesSearch =
38
- searchQuery === '' ||
39
- config.name.toLowerCase().includes(searchQuery.toLowerCase());
132
+ // -- Feature cards (rich content for FeatureCard) --
133
+ const featureCards = [
134
+ {
135
+ icon: Zap,
136
+ title: t('templates.home.features.feature1.title'),
137
+ subtitle: 'Entity-first architecture',
138
+ content: [
139
+ 'Define once with defineEntity()',
140
+ 'Auto-generated CRUD operations',
141
+ 'Type-safe forms and validation',
142
+ ],
143
+ },
144
+ {
145
+ icon: Shield,
146
+ title: t('templates.home.features.feature2.title'),
147
+ subtitle: 'Security built in, not bolted on',
148
+ content: [
149
+ 'Role-based access control',
150
+ 'PII encryption at rest',
151
+ 'Rate limiting and anomaly detection',
152
+ ],
153
+ },
154
+ {
155
+ icon: Rocket,
156
+ title: t('templates.home.features.feature3.title'),
157
+ subtitle: 'Ship fast, stay consistent',
158
+ content: [
159
+ '5 themes with design tokens',
160
+ '30+ production components',
161
+ 'Lazy-loaded advanced components',
162
+ ],
163
+ },
164
+ ];
40
165
 
41
- return matchesSearch;
42
- }).sort((a, b) => a.name.localeCompare(b.name));
43
- }, [selectedTab, searchQuery]);
166
+ // -- Roadmap steps --
167
+ const steps: RoadmapStep[] = [
168
+ {
169
+ phase: t('templates.home.howItWorks.step1.title'),
170
+ icon: UserPlus,
171
+ title: t('templates.home.howItWorks.step1.title'),
172
+ subtitle: t('templates.home.howItWorks.step1.description'),
173
+ },
174
+ {
175
+ phase: t('templates.home.howItWorks.step2.title'),
176
+ icon: Settings,
177
+ title: t('templates.home.howItWorks.step2.title'),
178
+ subtitle: t('templates.home.howItWorks.step2.description'),
179
+ },
180
+ {
181
+ phase: t('templates.home.howItWorks.step3.title'),
182
+ icon: Play,
183
+ title: t('templates.home.howItWorks.step3.title'),
184
+ subtitle: t('templates.home.howItWorks.step3.description'),
185
+ },
186
+ ];
44
187
 
45
- const cssFamilies = getCSSFamilies();
188
+ // -- SplitReveal stat cards --
189
+ const statCards = [
190
+ {
191
+ title: '12+ Components',
192
+ description: 'Atomic, advanced, and layout components ready to compose',
193
+ },
194
+ { title: '4 Essences', description: 'SaaS - Brutalist - Luxury - Retro' },
195
+ {
196
+ title: '100% Typed',
197
+ description: 'Full TypeScript coverage with strict mode',
198
+ },
199
+ {
200
+ title: 'Design System',
201
+ description:
202
+ 'Full Design System with tokens and components when you can personalize anything',
203
+ },
204
+ ];
46
205
 
47
206
  return (
48
- <Section
49
- title={
50
- cssFamilies.find((f) => f.id === selectedTab)?.label ||
51
- 'Components'
52
- }
53
- subtitle={`${componentsInTab.length} components`}
54
- >
55
- <Grid cols="auto-fit" minColWidth="240px">
56
- {componentsInTab.map((config) => {
57
- const isFullPageComponent = config.cssFamily === 'layout';
58
- return (
59
- <Card
60
- key={config.id}
61
- title={config.name}
62
- onClick={() =>
63
- isFullPageComponent
64
- ? navigate('/full')
65
- : navigate(`/component/${config.id}`)
66
- }
67
- >
68
- <Stack direction="row" justify="end">
69
- <Badge variant="secondary">
70
- {cssFamilies.find((f) => f.id === config.cssFamily)?.label || config.cssFamily}
71
- </Badge>
72
- </Stack>
73
- </Card>
74
- );
75
- })}
76
- </Grid>
77
- </Section>
207
+ <PageContainer>
208
+ {/* 1. Hero — clean, no buttons */}
209
+ <HeroSection
210
+ badge={t('templates.home.hero.badge')}
211
+ title={t('templates.home.hero.title')}
212
+ subtitle={t('templates.home.hero.subtitle')}
213
+ />
214
+
215
+ {/* 2. Features — above the fold, FeatureCard with rich content */}
216
+ <Section
217
+ title={t('templates.home.features.title')}
218
+ gridCols={[1, 1, 3, 3]}
219
+ collapsible
220
+ defaultOpen
221
+ >
222
+ {featureCards.map((f, i) => (
223
+ <FeatureCard
224
+ key={f.title}
225
+ variant={CARD_VARIANT.GLASS}
226
+ icon={f.icon}
227
+ title={f.title}
228
+ subtitle={f.subtitle}
229
+ content={f.content}
230
+ />
231
+ ))}
232
+ </Section>
233
+
234
+ {/* 3. SplitReveal — slow, deliberate entrance */}
235
+ <Section title="Framework at a Glance" tone="muted">
236
+ <SplitReveal
237
+ left={
238
+ <Stack gap="medium">
239
+ <Badge variant={BADGE_VARIANT.ACCENT}>Why DoNotDev?</Badge>
240
+ <Text level="h2">Built for Real Products</Text>
241
+ <Text level="body" variant="muted">
242
+ Production-grade CRUD, auth, billing, and UI — all type-safe,
243
+ theme-aware, and ready to ship. Stop rebuilding the same
244
+ plumbing.
245
+ </Text>
246
+ </Stack>
247
+ }
248
+ right={statCards}
249
+ useStatCards
250
+ stagger={400}
251
+ duration={1000}
252
+ distance={12}
253
+ />
254
+ </Section>
255
+
256
+ {/* 4. Roadmap — ghost tone */}
257
+ <Section title={t('templates.home.howItWorks.title')} tone="ghost">
258
+ <Roadmap steps={steps} />
259
+ </Section>
260
+
261
+ {/* 5. Testimonials Marquee — muted tone, showcases Marquee component */}
262
+ <Section title="What Developers Say" tone="muted">
263
+ <Badge
264
+ variant={BADGE_VARIANT.MUTED}
265
+ style={{ marginBottom: 'var(--gap-md)', display: 'inline-block' }}
266
+ >
267
+ Fictional testimonials — this is a demo showcase
268
+ </Badge>
269
+ <Marquee
270
+ items={testimonials}
271
+ renderItem={(_item) => {
272
+ const t = _item as (typeof testimonials)[number];
273
+ return (
274
+ <Card style={{ minWidth: 280, maxWidth: 320 }}>
275
+ <Stack gap="tight" style={{ padding: 'var(--gap-md)' }}>
276
+ <Quote
277
+ style={{
278
+ width: 'var(--icon-sm)',
279
+ height: 'var(--icon-sm)',
280
+ color: 'var(--muted-foreground)',
281
+ opacity: 0.5,
282
+ }}
283
+ />
284
+ <Text level="small" italic>
285
+ &ldquo;{t.text}&rdquo;
286
+ </Text>
287
+ <Stack gap="none">
288
+ <Text level="small" weight="semibold">
289
+ {t.name}
290
+ </Text>
291
+ <Text level="caption" variant="muted">
292
+ {t.role}
293
+ </Text>
294
+ </Stack>
295
+ </Stack>
296
+ </Card>
297
+ );
298
+ }}
299
+ speed={300}
300
+ pauseOnHover
301
+ gap="medium"
302
+ behavior="infinite"
303
+ ariaLabel="Developer testimonials"
304
+ />
305
+ </Section>
306
+
307
+ {/* 6. Component Showcase Carousel — ghost tone */}
308
+ <Section title="Component Showcase" tone="ghost">
309
+ <Badge
310
+ variant={BADGE_VARIANT.MUTED}
311
+ style={{ marginBottom: 'var(--gap-md)', display: 'inline-block' }}
312
+ >
313
+ Swipe or use arrows — this Carousel is a framework component
314
+ </Badge>
315
+ <Carousel
316
+ gap="medium"
317
+ items={showcaseItems}
318
+ renderItem={(_item, _index, isActive) => {
319
+ const item = _item as (typeof showcaseItems)[number];
320
+ return (
321
+ <Card
322
+ variant={item.variant}
323
+ icon={item.icon}
324
+ title={item.title}
325
+ content={item.description}
326
+ style={{
327
+ opacity: isActive ? 1 : 0.6,
328
+ transition: 'opacity var(--dur-normal)',
329
+ }}
330
+ />
331
+ );
332
+ }}
333
+ slidesToShow={[1, 2, 3, 4]}
334
+ showArrows
335
+ infinite
336
+ aria-label="Component showcase carousel"
337
+ />
338
+ </Section>
339
+
340
+ {/* 7. CTA — accent tone */}
341
+ <CallToAction
342
+ tone="accent"
343
+ title={t('templates.home.cta.title')}
344
+ subtitle={t('templates.home.cta.subtitle')}
345
+ primaryAction={
346
+ <Button variant={BUTTON_VARIANT.PRIMARY}>
347
+ {t('templates.home.cta.primaryAction')}
348
+ </Button>
349
+ }
350
+ secondaryAction={
351
+ <Button variant={BUTTON_VARIANT.OUTLINE}>
352
+ {t('templates.home.cta.secondaryAction')}
353
+ </Button>
354
+ }
355
+ />
356
+ </PageContainer>
78
357
  );
79
- }
358
+ }
@@ -0,0 +1,47 @@
1
+ // apps/demo/src/pages/OnboardingPage.tsx
2
+
3
+ import { UserPlus } from 'lucide-react';
4
+
5
+ import { EntityWorkflow } from '@donotdev/ui';
6
+
7
+ import { onboardingWorkflow } from '../entities/onboarding';
8
+
9
+ import type { PageMeta } from '@donotdev/core';
10
+
11
+ export const meta: PageMeta = {
12
+ icon: <UserPlus />,
13
+ title: 'Onboarding Wizard',
14
+ preset: 'admin',
15
+ };
16
+
17
+ /**
18
+ * Onboarding Wizard Demo — shows multi-step workflow with:
19
+ * - Step navigation via Stepper
20
+ * - Per-step entity forms
21
+ * - Skippable steps (Preferences)
22
+ * - Conditional steps (Billing only if company size > 10)
23
+ * - Auto-persistence to localStorage
24
+ */
25
+ export default function OnboardingPage() {
26
+ return (
27
+ <div style={{ maxWidth: 640, margin: '0 auto' }}>
28
+ <h1>Customer Onboarding</h1>
29
+ <p
30
+ style={{
31
+ color: 'var(--foreground-muted)',
32
+ marginBottom: 'var(--gap-lg)',
33
+ }}
34
+ >
35
+ Multi-step workflow with conditional steps and auto-save. Try setting
36
+ company size &gt; 10 to see the Billing step appear.
37
+ </p>
38
+
39
+ <EntityWorkflow
40
+ workflow={onboardingWorkflow}
41
+ onComplete={async (data) => {
42
+ alert(`Onboarding complete!\n\n${JSON.stringify(data, null, 2)}`);
43
+ }}
44
+ />
45
+ </div>
46
+ );
47
+ }
@@ -0,0 +1,41 @@
1
+ // apps/demo/src/pages/PricingPage.tsx
2
+
3
+ import { CreditCard } from 'lucide-react';
4
+
5
+ import { SubscriptionTemplate } from '@donotdev/templates';
6
+
7
+ import type { PageMeta } from '@donotdev/core';
8
+
9
+ export const meta: PageMeta = {
10
+ icon: <CreditCard />,
11
+ hideFromMenu: true,
12
+ };
13
+
14
+ export default function PricingPage() {
15
+ return (
16
+ <SubscriptionTemplate
17
+ namespace="demo"
18
+ plans={[
19
+ {
20
+ id: 'free',
21
+ name: 'Free',
22
+ price: '0€',
23
+ currency: 'eur',
24
+ priceId: 'price_free',
25
+ interval: 'month',
26
+ features: ['1 project', 'Community support'],
27
+ },
28
+ {
29
+ id: 'pro',
30
+ name: 'Pro',
31
+ price: '29€',
32
+ currency: 'eur',
33
+ priceId: 'price_pro',
34
+ interval: 'month',
35
+ popular: true,
36
+ features: ['Unlimited projects', 'Priority support', 'Custom domain'],
37
+ },
38
+ ]}
39
+ />
40
+ );
41
+ }
@@ -0,0 +1,19 @@
1
+ // apps/demo/src/pages/ProductsPage.tsx
2
+
3
+ import { Package } from 'lucide-react';
4
+
5
+ import { ProductCardListTemplate } from '@donotdev/templates';
6
+
7
+ import { productEntity } from '../entities/product';
8
+
9
+ import type { PageMeta } from '@donotdev/core';
10
+
11
+ export const meta: PageMeta = {
12
+ icon: <Package />,
13
+ auth: true,
14
+ preset: 'admin',
15
+ };
16
+
17
+ export default function ProductsPage() {
18
+ return <ProductCardListTemplate entity={productEntity} />;
19
+ }
@@ -0,0 +1,18 @@
1
+ // apps/demo/src/pages/ProfilePage.tsx
2
+
3
+ import { User } from 'lucide-react';
4
+
5
+ import { ProfileTemplate } from '@donotdev/templates';
6
+
7
+ import type { PageMeta } from '@donotdev/core';
8
+
9
+ export const meta: PageMeta = {
10
+ icon: <User />,
11
+ auth: true,
12
+ preset: 'admin',
13
+ hideFromMenu: true,
14
+ };
15
+
16
+ export default function ProfilePage() {
17
+ return <ProfileTemplate billingPath="/pricing" />;
18
+ }
@@ -0,0 +1,17 @@
1
+ // apps/demo/src/pages/SettingsPage.tsx
2
+
3
+ import { Settings } from 'lucide-react';
4
+
5
+ import { SettingsTemplate } from '@donotdev/templates';
6
+
7
+ import type { PageMeta } from '@donotdev/core';
8
+
9
+ export const meta: PageMeta = {
10
+ icon: <Settings />,
11
+ auth: true,
12
+ preset: 'admin',
13
+ };
14
+
15
+ export default function SettingsPage() {
16
+ return <SettingsTemplate />;
17
+ }
@@ -0,0 +1,118 @@
1
+ // apps/demo/src/pages/ShowcaseDetailPage.tsx
2
+
3
+ import { useEffect, useMemo } from 'react';
4
+
5
+ import { Badge, Grid, Stack, Text } from '@donotdev/components';
6
+ import { PageContainer, useNavigate, useParams } from '@donotdev/ui';
7
+
8
+ import {
9
+ COMPONENT_CONFIGS,
10
+ getCSSFamilies,
11
+ } from './components/componentConfig';
12
+ import { ComponentRenderer } from './components/ComponentRenderer';
13
+
14
+ import type { PageMeta } from '@donotdev/core';
15
+ import type { ComponentConfig } from './components/componentConfig';
16
+
17
+ export const meta: PageMeta = {
18
+ route: '/showcase/:id',
19
+ hideFromMenu: true,
20
+ preset: 'admin',
21
+ };
22
+
23
+ export default function ShowcaseDetailPage() {
24
+ const { id } = useParams();
25
+ const navigate = useNavigate();
26
+
27
+ const config = useMemo(() => {
28
+ return COMPONENT_CONFIGS.find((c) => c.id === id);
29
+ }, [id]);
30
+
31
+ const cssFamilies = getCSSFamilies();
32
+
33
+ useEffect(() => {
34
+ if (!config) navigate('/showcase');
35
+ }, [config, navigate]);
36
+
37
+ if (!config) return null;
38
+
39
+ const generateVariants = (
40
+ config: ComponentConfig
41
+ ): Array<Record<string, any>> => {
42
+ const variants: Array<Record<string, any>> = [{}];
43
+
44
+ const dimensions = [
45
+ 'variant',
46
+ 'size',
47
+ 'tone',
48
+ 'type',
49
+ 'side',
50
+ 'mode',
51
+ ] as const;
52
+
53
+ dimensions.forEach((dim) => {
54
+ const values = config.variants[dim];
55
+ if (values?.length) {
56
+ const newVariants: Array<Record<string, any>> = [];
57
+ variants.forEach((base) => {
58
+ values.forEach((value) => {
59
+ newVariants.push({ ...base, [dim]: value });
60
+ });
61
+ });
62
+ variants.length = 0;
63
+ variants.push(...newVariants);
64
+ }
65
+ });
66
+
67
+ return variants.length > 0 ? variants : [{}];
68
+ };
69
+
70
+ const allVariants = generateVariants(config);
71
+
72
+ return (
73
+ <PageContainer>
74
+ <Stack gap="large" align="center">
75
+ <Stack gap="tight" align="center">
76
+ <Text level="h2">{config.name}</Text>
77
+ <Badge variant="outline">
78
+ {cssFamilies.find((f) => f.id === config.cssFamily)?.label ||
79
+ config.cssFamily}
80
+ </Badge>
81
+ </Stack>
82
+
83
+ <Grid cols={[1, 1, 2, 3]} gap="large">
84
+ {allVariants.map((variantProps, idx) => {
85
+ const variantLabels = Object.entries(variantProps)
86
+ .filter(([_, v]) => v)
87
+ .map(([k, v]) => `${k}: ${v}`);
88
+
89
+ return (
90
+ <Stack key={idx} align="center">
91
+ {variantLabels.length > 0 && (
92
+ <Stack
93
+ direction="row"
94
+ gap="tight"
95
+ wrap="wrap"
96
+ justify="center"
97
+ >
98
+ {variantLabels.map((label) => (
99
+ <Badge key={label} variant="secondary">
100
+ {label}
101
+ </Badge>
102
+ ))}
103
+ </Stack>
104
+ )}
105
+ <Stack align="center" justify="center">
106
+ <ComponentRenderer
107
+ config={config}
108
+ variantProps={variantProps}
109
+ />
110
+ </Stack>
111
+ </Stack>
112
+ );
113
+ })}
114
+ </Grid>
115
+ </Stack>
116
+ </PageContainer>
117
+ );
118
+ }