@donotdev/cli 0.0.19 → 0.0.21

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 (128) hide show
  1. package/README.md +31 -0
  2. package/dependencies-matrix.json +205 -50
  3. package/dist/bin/commands/agent-setup.js +2 -2
  4. package/dist/bin/commands/build.js +6 -6
  5. package/dist/bin/commands/bump.js +495 -70
  6. package/dist/bin/commands/cacheout.js +6 -6
  7. package/dist/bin/commands/coach.js +6 -6
  8. package/dist/bin/commands/create-app.js +24 -16
  9. package/dist/bin/commands/create-project.js +114 -18
  10. package/dist/bin/commands/db.js +142136 -0
  11. package/dist/bin/commands/deploy.js +354 -126
  12. package/dist/bin/commands/dev.js +6 -6
  13. package/dist/bin/commands/doctor.js +140 -33
  14. package/dist/bin/commands/emu.js +6 -6
  15. package/dist/bin/commands/format.js +6 -6
  16. package/dist/bin/commands/get-demo.js +11 -6
  17. package/dist/bin/commands/make-admin.js +14210 -13770
  18. package/dist/bin/commands/preview.js +6 -6
  19. package/dist/bin/commands/seed.js +142426 -0
  20. package/dist/bin/commands/setup-cicd.js +8904 -0
  21. package/dist/bin/commands/setup.js +259 -212
  22. package/dist/bin/commands/staging.js +361 -127
  23. package/dist/bin/commands/sync-secrets.js +55 -33
  24. package/dist/bin/commands/type-check.js +16 -10
  25. package/dist/bin/commands/wai.js +6 -6
  26. package/dist/bin/dndev.js +194 -188
  27. package/dist/bin/donotdev.js +139 -189
  28. package/dist/index.js +468 -144
  29. package/package.json +1 -1
  30. package/templates/app-demo/.env.example +1 -0
  31. package/templates/{root-consumer → app-demo}/entities/ExampleEntity.ts.example +15 -9
  32. package/templates/app-demo/index.html.example +1 -1
  33. package/templates/app-demo/public/apple-touch-icon.png.example +0 -0
  34. package/templates/app-demo/public/favicon.svg.example +1 -0
  35. package/templates/app-demo/public/icon-192x192.png.example +0 -0
  36. package/templates/app-demo/public/icon-512x512.png.example +0 -0
  37. package/templates/app-demo/src/App.tsx.example +3 -1
  38. package/templates/app-demo/src/config/app.ts.example +1 -0
  39. package/templates/app-demo/src/entities/booking.ts.example +75 -0
  40. package/templates/app-demo/src/entities/onboarding.ts.example +160 -0
  41. package/templates/app-demo/src/entities/product.ts.example +12 -0
  42. package/templates/app-demo/src/entities/quote.ts.example +70 -0
  43. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +28 -1
  44. package/templates/app-demo/src/pages/ConditionalFormPage.tsx.example +88 -0
  45. package/templates/app-demo/src/pages/DashboardPage.tsx.example +2 -0
  46. package/templates/app-demo/src/pages/HomePage.tsx.example +355 -2
  47. package/templates/app-demo/src/pages/OnboardingPage.tsx.example +47 -0
  48. package/templates/app-demo/src/pages/PricingPage.tsx.example +28 -1
  49. package/templates/app-demo/src/pages/ProductsPage.tsx.example +2 -0
  50. package/templates/app-demo/src/pages/ProfilePage.tsx.example +2 -0
  51. package/templates/app-demo/src/pages/SettingsPage.tsx.example +2 -0
  52. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +22 -16
  53. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +3 -1
  54. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +147 -51
  55. package/templates/app-demo/src/pages/components/ComponentsData.tsx.example +103 -21
  56. package/templates/app-demo/src/pages/components/componentConfig.ts.example +139 -59
  57. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +12 -1
  58. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +10 -1
  59. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +10 -1
  60. package/templates/app-demo/src/themes.css.example +289 -77
  61. package/templates/app-demo/stats.html.example +4949 -0
  62. package/templates/app-dndev/index.html.example +164 -0
  63. package/templates/app-dndev/public/logo.svg.example +1 -0
  64. package/templates/app-dndev/public/manifest.json.example +10 -0
  65. package/templates/app-dndev/src/App.tsx.example +35 -0
  66. package/templates/app-dndev/src/components/CockpitLayout.css.example +181 -0
  67. package/templates/app-dndev/src/components/CockpitLayout.tsx.example +209 -0
  68. package/templates/app-dndev/src/components/Kanban.css.example +385 -0
  69. package/templates/app-dndev/src/components/ModeToggle.tsx.example +32 -0
  70. package/templates/app-dndev/src/components/OverlaySlot.tsx.example +68 -0
  71. package/templates/app-dndev/src/components/TerminalPanel.css.example +228 -0
  72. package/templates/app-dndev/src/components/TerminalPanel.tsx.example +714 -0
  73. package/templates/app-dndev/src/components/markdown-prose.css.example +49 -0
  74. package/templates/app-dndev/src/components/phases/CaptainLog.tsx.example +107 -0
  75. package/templates/app-dndev/src/components/phases/ContextTabs.tsx.example +352 -0
  76. package/templates/app-dndev/src/components/phases/PhaseCard.tsx.example +126 -0
  77. package/templates/app-dndev/src/components/phases/PhaseDetail.tsx.example +147 -0
  78. package/templates/app-dndev/src/components/phases/ReviewPanel.tsx.example +115 -0
  79. package/templates/app-dndev/src/components/phases/phaseData.ts.example +366 -0
  80. package/templates/app-dndev/src/config/app.ts.example +103 -0
  81. package/templates/app-dndev/src/config/commands.ts.example +171 -0
  82. package/templates/app-dndev/src/config/legal.ts.example +170 -0
  83. package/templates/app-dndev/src/config/providers.ts.example +7 -0
  84. package/templates/app-dndev/src/globals.css.example +10 -0
  85. package/templates/app-dndev/src/hooks/useDndevFile.ts.example +144 -0
  86. package/templates/app-dndev/src/main.tsx.example +21 -0
  87. package/templates/app-dndev/src/pages/BoardPage.tsx.example +640 -0
  88. package/templates/app-dndev/src/pages/GrillPage.tsx.example +658 -0
  89. package/templates/app-dndev/src/pages/HomePage.tsx.example +347 -0
  90. package/templates/app-dndev/src/pages/NotFoundPage.tsx.example +33 -0
  91. package/templates/app-dndev/src/pages/PhasesPage.tsx.example +137 -0
  92. package/templates/app-dndev/src/pages/SettingsPage.tsx.example +64 -0
  93. package/templates/app-dndev/src/pages/legal/LegalNoticePage.tsx.example +75 -0
  94. package/templates/app-dndev/src/pages/legal/PrivacyPage.tsx.example +69 -0
  95. package/templates/app-dndev/src/pages/legal/TermsPage.tsx.example +71 -0
  96. package/templates/app-dndev/src/stores/dndevStore.ts.example +386 -0
  97. package/templates/app-dndev/src/themes.css.example +161 -0
  98. package/templates/app-dndev/terminal-sidecar.cjs.example +341 -0
  99. package/templates/app-dndev/tsconfig.json.example +9 -0
  100. package/templates/app-dndev/vite.config.ts.example +24 -0
  101. package/templates/app-vite/index.html.example +1 -1
  102. package/templates/functions-supabase/supabase/functions/.env.example +0 -2
  103. package/templates/root-consumer/.claude/commands/grill.md.example +86 -8
  104. package/templates/root-consumer/.dndev.secrets.example +32 -0
  105. package/templates/root-consumer/.gitignore.example +3 -0
  106. package/templates/root-consumer/AI.md.example +4 -0
  107. package/templates/root-consumer/entities/index.ts.example +2 -5
  108. package/templates/root-consumer/guides/dndev/COMPONENTS_ATOMIC.md.example +4 -0
  109. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +23 -20
  110. package/templates/root-consumer/guides/dndev/INDEX.md.example +1 -0
  111. package/templates/root-consumer/guides/dndev/SETUP_BILLING.md.example +3 -7
  112. package/templates/root-consumer/guides/dndev/SETUP_CICD.md.example +115 -0
  113. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +41 -0
  114. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +13 -18
  115. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +17 -12
  116. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +185 -251
  117. package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +26 -8
  118. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +66 -49
  119. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +6 -5
  120. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +9 -9
  121. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +1 -1
  122. package/templates/root-consumer/guides/wai-way/blueprints/4_configure.md.example +7 -6
  123. package/templates/root-consumer/guides/wai-way/context_map.json.example +51 -20
  124. package/templates/root-consumer/guides/wai-way/hld_template.md.example +138 -0
  125. package/templates/root-consumer/guides/wai-way/lld_template.md.example +103 -0
  126. package/templates/root-consumer/guides/wai-way/prd_template.md.example +140 -0
  127. /package/templates/{root-consumer → app-demo}/entities/Contact.ts.example +0 -0
  128. /package/templates/{root-consumer → app-demo}/entities/demo.ts.example +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,
@@ -0,0 +1 @@
1
+ VITE_AUTH_PARTNERS=password, google, github, apple, discord, facebook, linkedin, reddit, twitch, twitter, microsoft, spotify, yahoo
@@ -32,13 +32,16 @@ export const productEntity = defineEntity({
32
32
  listCardFields: ['images', 'name', 'price', 'category'],
33
33
 
34
34
  // ==========================================================================
35
- // ACCESS RULES - Who can do what
35
+ // ACCESS RULES - Who can do what (maps to Supabase RLS policies)
36
36
  // ==========================================================================
37
37
  //
38
38
  // 'guest' → Anyone (including not logged in)
39
39
  // 'user' → Any logged-in user
40
- // 'owner' → Only the document owner (createdById matches)
41
40
  // 'admin' → Only admin role
41
+ // 'super' → Only super admin
42
+ //
43
+ // NOTE: These are DB-level roles. For owner-based logic, use field-level
44
+ // 'editable' / 'visibility' settings (see FIELD DEFINITIONS below).
42
45
  //
43
46
  access: {
44
47
  create: 'admin', // Only admins can create products
@@ -67,16 +70,19 @@ export const productEntity = defineEntity({
67
70
  // 'images' → Image upload (multiple)
68
71
  // 'reference' → Link to another entity
69
72
  //
70
- // VISIBILITY:
71
- // 'guest' → Everyone can see this field
72
- // 'user' → Only logged-in users
73
- // 'owner' → Only document owner
74
- // 'admin' → Only admins
73
+ // VISIBILITY (field-level, UI only):
74
+ // 'guest' → Everyone can see this field
75
+ // 'user' → Only logged-in users
76
+ // 'admin' → Only admins
77
+ // 'super' → Only super admins
78
+ // 'hidden' → Never sent to client (server-only)
75
79
  //
76
- // EDITABLE:
80
+ // EDITABLE (field-level, UI only):
77
81
  // 'admin' → Only admins can edit
78
- // 'owner' → Only owner can edit
82
+ // 'owner' → Only document creator can edit
83
+ // 'user' → Any authenticated user can edit
79
84
  // 'create-only' → Set on creation, read-only after
85
+ // false → Never editable (read-only)
80
86
  //
81
87
  fields: {
82
88
  // ==========================================================================
@@ -20,7 +20,7 @@
20
20
  box-sizing: border-box;
21
21
  }
22
22
  body {
23
- font-family: 'Inter', var(--font-family, ui-sans-serif, system-ui, -apple-system, sans-serif);
23
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
24
24
  line-height: 1.5;
25
25
  -webkit-font-smoothing: antialiased;
26
26
  -moz-osx-font-smoothing: grayscale;
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" xmlns:v="https://vecta.io/nano"><path d="M11.995 68.133c-.747.14-2.114 1.276-2.986 2.409l-1.557 2.199-.062 104.273.684 251.717c.935 2.835 3.423 4.749 6.347 4.89 2.366.142 3.61-.566 10.767-5.599l42.311-30.054L112.3 366.14l16.366-11.768c3.234-2.268 6.098-4.749 6.346-5.599 1.369-3.828 9.271-32.679 9.023-32.891-.124-.213-1.743.78-3.547 2.198-1.803 1.347-8.773 6.309-15.432 10.916L87.1 355.862l-24.891 17.65-23.831 16.729c-5.413 3.898-10.143 7.017-10.454 7.017-.685 0-.809-291.837-.063-292.334.249-.141 1.619.497 3.049 1.559l51.521 37.711 18.668 13.61 20.222 14.674 13.69 9.996 9.333 6.734 12.756 9.215c10.455 7.798 15.992 11.767 16.553 11.908.374.073 1.99-4.889 3.609-11.058l3.048-11.202-5.537-4.038-10.641-7.799c-2.863-1.984-10.391-7.584-16.8-12.405l-23.21-17.154-20.721-15.24L89.4 121.157c-2.613-1.986-7.653-5.671-11.2-8.223L23.506 73.096c-6.471-4.679-8.774-5.671-11.512-4.962l.001-.001zm235.829 4.466c-1.057.708-2.302 2.055-2.737 2.977-.622 1.276-.809 14.673-.746 62.733l.062 61.104 4.915 8.01 10.206 16.871 5.225 8.861.187-62.308 1.057-61.812c.56.212 6.098 4.111 12.321 8.648l43.806 31.97c1.307.991 1.431.708 5.973-9.641l4.667-10.705-1.618-1.346-14.747-10.845-20.844-15.313-36.65-26.864c-5.788-4.182-7.841-4.608-11.077-2.34zm-34.784 196.85l-7.279 15.807-11.511 25.166c.123.141 5.351-3.474 11.697-7.939l18.356-13.042 8.027-5.813c1.057-.922.685-1.701-6.347-13.469l-7.466-12.546-5.477 11.838v-.002z" fill="var(--primary,#dc143c)"/><path d="M376.752 57.145l-4.977 11.2c-1.432 2.907-4.792 10.066-7.468 15.95l-9.955 21.619-25.388 54.583-11.2 24.101-20.658 43.949-11.7 24.81-7.84 16.304c-.809 1.347-.621 1.631-15.679-23.747l-26.072-43.949-22.213-37.71c-8.587-14.815-10.267-16.73-12.322-14.319-.435.566-2.676 8.009-4.978 16.586l-22.711 82.228-13.378 47.494-8.153 29.064-18.232 64.86-12.133 43.382-4.355 16.162c.186 0 3.671-7.443 14.871-31.898l10.578-22.684 8.088-17.013 8.774-18.43 9.771-20.556 7.901-16.659 9.333-19.848 9.957-21.267 10.765-23.038c6.844-14.957 9.397-20.061 10.08-20.273.374-.142 3.485 4.606 6.968 10.562l24.828 41.255 31.981 52.809c5.289 8.932 6.846 11.06 8.153 11.2.87.142 1.929-.212 2.302-.779.685-.851 19.6-65.499 44.054-150.421l25.823-88.889 17.798-62.168c-.125-.141-1.308 2.34-2.615 5.53h.002z" fill="var(--accent,#ffd700)"/><path d="M359.081 153.904l-3.111 11.555c-1.369 4.89-2.302 9.074-2.053 9.287s5.041 3.757 10.703 7.869l33.289 24.314 37.645 27.505 19.601 14.318 6.409 4.536c2.489 1.49 5.538-.991-32.542 26.369l-38.269 27.432-31.236 22.402-33.913 24.456-28.187 20.273-12.134 8.648c-10.019 7.16-19.413 13.681-19.848 13.681-.188 0-.374-14.248-.374-31.757v-31.686l-4.419-7.088-10.019-16.518c-3.111-5.102-5.849-9.356-6.098-9.356s-.375 11.909-.249 26.37l.249 64.223v37.711l2.054 2.623c1.866 2.268 2.489 2.553 4.914 2.553 3.237 0 4.169-.568 18.855-11.202l76.535-55.291 21.78-15.807 120.403-86.411c3.67-2.552 5.102-4.748 5.475-8.434.188-2.409 0-3.971-.746-5.599-1.244-2.623-2.677-3.686-48.908-37.711l-51.023-37.642-14.624-10.774-12.88-9.427c-2.986-2.199-5.724-4.041-6.035-4.041-.374 0-.934 1.206-1.245 2.622l.001-.003z" fill="var(--primary,#dc143c)"/></svg>
@@ -26,5 +26,7 @@ import { appConfig } from './config/app';
26
26
  * @author AMBROISE PARK Consulting
27
27
  */
28
28
  export function App() {
29
- return <ViteAppProviders config={appConfig} layout={{ breadcrumbs: 'smart' }} />;
29
+ return (
30
+ <ViteAppProviders config={appConfig} layout={{ breadcrumbs: 'smart' }} />
31
+ );
30
32
  }
@@ -1,3 +1,4 @@
1
+ // apps/demo/src/config/app.ts
1
2
  /**
2
3
  * @fileoverview Application configuration
3
4
  * @description Defines application metadata, layout preset, and feature flags
@@ -0,0 +1,75 @@
1
+ // apps/demo/src/entities/booking.ts
2
+
3
+ import { defineEntity, when } from '@donotdev/core';
4
+
5
+ /**
6
+ * Booking entity — demonstrates complex conditional logic.
7
+ *
8
+ * - groupSize: visible only for group bookings
9
+ * - companyName: visible only for corporate bookings
10
+ * - invoiceAddress: visible for corporate OR group with 10+ people
11
+ */
12
+ export const bookingEntity = defineEntity({
13
+ name: 'Booking',
14
+ collection: 'bookings',
15
+ fields: {
16
+ bookingType: {
17
+ name: 'bookingType',
18
+ type: 'select',
19
+ label: 'Booking Type',
20
+ visibility: 'user',
21
+ validation: {
22
+ required: true,
23
+ options: [
24
+ { value: 'individual', label: 'Individual' },
25
+ { value: 'group', label: 'Group (5+)' },
26
+ { value: 'corporate', label: 'Corporate' },
27
+ ],
28
+ },
29
+ },
30
+ groupSize: {
31
+ name: 'groupSize',
32
+ type: 'number',
33
+ label: 'Number of People',
34
+ visibility: 'user',
35
+ conditions: {
36
+ visible: when('bookingType').equals('group'),
37
+ required: when('bookingType').equals('group'),
38
+ },
39
+ },
40
+ companyName: {
41
+ name: 'companyName',
42
+ type: 'text',
43
+ label: 'Company Name',
44
+ visibility: 'user',
45
+ conditions: {
46
+ visible: when('bookingType').equals('corporate'),
47
+ required: when('bookingType').equals('corporate'),
48
+ },
49
+ },
50
+ invoiceAddress: {
51
+ name: 'invoiceAddress',
52
+ type: 'address',
53
+ label: 'Invoice Address',
54
+ visibility: 'user',
55
+ conditions: {
56
+ visible: when('bookingType')
57
+ .equals('corporate')
58
+ .or(when('groupSize').greaterThan(10)),
59
+ },
60
+ },
61
+ date: {
62
+ name: 'date',
63
+ type: 'date',
64
+ label: 'Booking Date',
65
+ visibility: 'user',
66
+ validation: { required: true },
67
+ },
68
+ notes: {
69
+ name: 'notes',
70
+ type: 'textarea',
71
+ label: 'Special Requests',
72
+ visibility: 'user',
73
+ },
74
+ },
75
+ });
@@ -0,0 +1,160 @@
1
+ // apps/demo/src/entities/onboarding.ts
2
+
3
+ import { defineEntity, when } from '@donotdev/core';
4
+ import { defineWorkflow } from '@donotdev/crud';
5
+
6
+ /**
7
+ * Entities for the Customer Onboarding workflow demo.
8
+ * Each entity represents one step in the wizard.
9
+ */
10
+
11
+ export const companyEntity = defineEntity({
12
+ name: 'Company',
13
+ collection: 'companies',
14
+ fields: {
15
+ name: {
16
+ name: 'name',
17
+ type: 'text',
18
+ label: 'Company Name',
19
+ visibility: 'user',
20
+ validation: { required: true, minLength: 2 },
21
+ },
22
+ industry: {
23
+ name: 'industry',
24
+ type: 'select',
25
+ label: 'Industry',
26
+ visibility: 'user',
27
+ validation: {
28
+ required: true,
29
+ options: [
30
+ { value: 'tech', label: 'Technology' },
31
+ { value: 'finance', label: 'Finance' },
32
+ { value: 'healthcare', label: 'Healthcare' },
33
+ { value: 'retail', label: 'Retail' },
34
+ { value: 'other', label: 'Other' },
35
+ ],
36
+ },
37
+ },
38
+ size: {
39
+ name: 'size',
40
+ type: 'number',
41
+ label: 'Number of Employees',
42
+ visibility: 'user',
43
+ validation: { required: true, min: 1 },
44
+ },
45
+ website: {
46
+ name: 'website',
47
+ type: 'url',
48
+ label: 'Website',
49
+ visibility: 'user',
50
+ },
51
+ },
52
+ });
53
+
54
+ export const contactEntity = defineEntity({
55
+ name: 'Contact',
56
+ collection: 'contacts',
57
+ fields: {
58
+ firstName: {
59
+ name: 'firstName',
60
+ type: 'text',
61
+ label: 'First Name',
62
+ visibility: 'user',
63
+ validation: { required: true },
64
+ },
65
+ lastName: {
66
+ name: 'lastName',
67
+ type: 'text',
68
+ label: 'Last Name',
69
+ visibility: 'user',
70
+ validation: { required: true },
71
+ },
72
+ email: {
73
+ name: 'email',
74
+ type: 'email',
75
+ label: 'Email',
76
+ visibility: 'user',
77
+ validation: { required: true },
78
+ },
79
+ phone: {
80
+ name: 'phone',
81
+ type: 'tel',
82
+ label: 'Phone',
83
+ visibility: 'user',
84
+ },
85
+ },
86
+ });
87
+
88
+ export const preferencesEntity = defineEntity({
89
+ name: 'Preferences',
90
+ collection: 'preferences',
91
+ fields: {
92
+ language: {
93
+ name: 'language',
94
+ type: 'select',
95
+ label: 'Language',
96
+ visibility: 'user',
97
+ validation: {
98
+ options: [
99
+ { value: 'en', label: 'English' },
100
+ { value: 'fr', label: 'French' },
101
+ { value: 'de', label: 'German' },
102
+ { value: 'es', label: 'Spanish' },
103
+ ],
104
+ },
105
+ },
106
+ notifications: {
107
+ name: 'notifications',
108
+ type: 'switch',
109
+ label: 'Enable Email Notifications',
110
+ visibility: 'user',
111
+ },
112
+ },
113
+ });
114
+
115
+ /**
116
+ * Customer Onboarding Workflow
117
+ *
118
+ * 4 steps:
119
+ * 1. Company Info (required)
120
+ * 2. Primary Contact (required)
121
+ * 3. Preferences (skippable)
122
+ * 4. Billing — only shown if company size > 10
123
+ */
124
+ export const onboardingWorkflow = defineWorkflow({
125
+ id: 'customer-onboarding',
126
+ name: 'Customer Onboarding',
127
+ persist: true,
128
+
129
+ steps: [
130
+ {
131
+ id: 'company',
132
+ title: 'Company Info',
133
+ entity: companyEntity,
134
+ fields: ['name', 'industry', 'size', 'website'],
135
+ },
136
+ {
137
+ id: 'contact',
138
+ title: 'Primary Contact',
139
+ entity: contactEntity,
140
+ fields: ['firstName', 'lastName', 'email', 'phone'],
141
+ },
142
+ {
143
+ id: 'preferences',
144
+ title: 'Preferences',
145
+ entity: preferencesEntity,
146
+ fields: ['language', 'notifications'],
147
+ allowSkip: true,
148
+ },
149
+ {
150
+ id: 'billing',
151
+ title: 'Billing',
152
+ description: 'Required for companies with more than 10 employees',
153
+ entity: companyEntity,
154
+ fields: ['website'], // placeholder — real app would have billing entity
155
+ conditions: {
156
+ visible: when('size').greaterThan(10),
157
+ },
158
+ },
159
+ ],
160
+ });
@@ -1,3 +1,5 @@
1
+ // apps/demo/src/entities/product.ts
2
+
1
3
  import { defineEntity } from '@donotdev/core';
2
4
 
3
5
  export const productEntity = defineEntity({
@@ -5,20 +7,28 @@ export const productEntity = defineEntity({
5
7
  collection: 'products',
6
8
  fields: {
7
9
  name: {
10
+ name: 'name',
11
+ label: 'Name',
8
12
  type: 'text',
9
13
  visibility: 'user',
10
14
  validation: { required: true, minLength: 3 },
11
15
  },
12
16
  description: {
17
+ name: 'description',
18
+ label: 'Description',
13
19
  type: 'textarea',
14
20
  visibility: 'user',
15
21
  },
16
22
  price: {
23
+ name: 'price',
24
+ label: 'Price',
17
25
  type: 'number',
18
26
  visibility: 'user',
19
27
  validation: { required: true, min: 0 },
20
28
  },
21
29
  category: {
30
+ name: 'category',
31
+ label: 'Category',
22
32
  type: 'select',
23
33
  visibility: 'user',
24
34
  validation: {
@@ -31,6 +41,8 @@ export const productEntity = defineEntity({
31
41
  },
32
42
  },
33
43
  image: {
44
+ name: 'image',
45
+ label: 'Image',
34
46
  type: 'image',
35
47
  visibility: 'user',
36
48
  },
@@ -0,0 +1,70 @@
1
+ // apps/demo/src/entities/quote.ts
2
+
3
+ import { defineEntity, when } from '@donotdev/core';
4
+
5
+ /**
6
+ * Insurance Quote entity — demonstrates conditional field visibility.
7
+ *
8
+ * - licensePlate: only visible when productType === 'car'
9
+ * - propertyAddress: only visible when productType === 'home'
10
+ * - estimatedValue: visible for car OR home (not health)
11
+ * - notes: disabled until productType is selected
12
+ */
13
+ export const quoteEntity = defineEntity({
14
+ name: 'Quote',
15
+ collection: 'quotes',
16
+ fields: {
17
+ productType: {
18
+ name: 'productType',
19
+ type: 'select',
20
+ label: 'Product',
21
+ visibility: 'user',
22
+ validation: {
23
+ required: true,
24
+ options: [
25
+ { value: 'health', label: 'Health Insurance' },
26
+ { value: 'car', label: 'Car Insurance' },
27
+ { value: 'home', label: 'Home Insurance' },
28
+ ],
29
+ },
30
+ },
31
+ licensePlate: {
32
+ name: 'licensePlate',
33
+ type: 'text',
34
+ label: 'License Plate',
35
+ visibility: 'user',
36
+ conditions: {
37
+ visible: when('productType').equals('car'),
38
+ required: when('productType').equals('car'),
39
+ },
40
+ },
41
+ propertyAddress: {
42
+ name: 'propertyAddress',
43
+ type: 'address',
44
+ label: 'Property Address',
45
+ visibility: 'user',
46
+ conditions: {
47
+ visible: when('productType').equals('home'),
48
+ required: when('productType').equals('home'),
49
+ },
50
+ },
51
+ estimatedValue: {
52
+ name: 'estimatedValue',
53
+ type: 'number',
54
+ label: 'Estimated Value',
55
+ visibility: 'user',
56
+ conditions: {
57
+ visible: when('productType').in(['car', 'home']),
58
+ },
59
+ },
60
+ notes: {
61
+ name: 'notes',
62
+ type: 'textarea',
63
+ label: 'Additional Notes',
64
+ visibility: 'user',
65
+ conditions: {
66
+ disabled: when('productType').notExists(),
67
+ },
68
+ },
69
+ },
70
+ });
@@ -1,3 +1,5 @@
1
+ // apps/demo/src/pages/ChangelogPage.tsx
2
+
1
3
  import { History } from 'lucide-react';
2
4
 
3
5
  import { WhatsNewTemplate } from '@donotdev/templates';
@@ -10,5 +12,30 @@ export const meta: PageMeta = {
10
12
  };
11
13
 
12
14
  export default function ChangelogPage() {
13
- return <WhatsNewTemplate />;
15
+ return (
16
+ <WhatsNewTemplate
17
+ changelog={[
18
+ {
19
+ version: '1.0.0',
20
+ date: '2026-01-15',
21
+ type: 'major',
22
+ title: 'Initial Release',
23
+ description: 'First public release of the demo app.',
24
+ changes: [
25
+ {
26
+ type: 'added',
27
+ items: [
28
+ 'Condition builder with when() API',
29
+ 'Multi-step workflow engine',
30
+ ],
31
+ },
32
+ {
33
+ type: 'changed',
34
+ items: ['Entity form renderer supports dynamic fields'],
35
+ },
36
+ ],
37
+ },
38
+ ]}
39
+ />
40
+ );
14
41
  }
@@ -0,0 +1,88 @@
1
+ // apps/demo/src/pages/ConditionalFormPage.tsx
2
+
3
+ import { SlidersHorizontal } from 'lucide-react';
4
+
5
+ import { Card, Tabs } from '@donotdev/components';
6
+ import { EntityFormRenderer } from '@donotdev/ui';
7
+
8
+ import { quoteEntity } from '../entities/quote';
9
+ import { bookingEntity } from '../entities/booking';
10
+
11
+ import type { PageMeta } from '@donotdev/core';
12
+
13
+ export const meta: PageMeta = {
14
+ icon: <SlidersHorizontal />,
15
+ title: 'Conditional Forms',
16
+ preset: 'admin',
17
+ };
18
+
19
+ /**
20
+ * Conditional Forms Demo — shows field visibility driven by `when()` conditions.
21
+ *
22
+ * Two examples:
23
+ * 1. Insurance Quote — fields appear/disappear based on product type
24
+ * 2. Booking — complex conditions with .or() combinator
25
+ */
26
+ export default function ConditionalFormPage() {
27
+ return (
28
+ <div style={{ maxWidth: 640, margin: '0 auto' }}>
29
+ <Card
30
+ title="Conditional Forms"
31
+ content="Fields appear, hide, or become required based on other field values. Powered by when() condition builder."
32
+ >
33
+ <Tabs
34
+ items={[
35
+ {
36
+ value: 'quote',
37
+ label: 'Insurance Quote',
38
+ content: (
39
+ <Card
40
+ title="Insurance Quote"
41
+ content='Select a product type to see conditional fields appear. "Car" shows license plate, "Home" shows address, both show estimated value.'
42
+ >
43
+ <EntityFormRenderer
44
+ entity={quoteEntity}
45
+ operation="create"
46
+ onSubmit={async (data) => {
47
+ alert(
48
+ `Quote submitted: ${JSON.stringify(data, null, 2)}`
49
+ );
50
+ }}
51
+ submitText="Get Quote"
52
+ cancelText={null}
53
+ warnOnUnsavedChanges={false}
54
+ hideVisibilityInfo
55
+ />
56
+ </Card>
57
+ ),
58
+ },
59
+ {
60
+ value: 'booking',
61
+ label: 'Booking',
62
+ content: (
63
+ <Card
64
+ title="Booking Form"
65
+ content='"Group" shows group size, "Corporate" shows company name. Invoice address appears for corporate OR groups with 10+ people.'
66
+ >
67
+ <EntityFormRenderer
68
+ entity={bookingEntity}
69
+ operation="create"
70
+ onSubmit={async (data) => {
71
+ alert(
72
+ `Booking submitted: ${JSON.stringify(data, null, 2)}`
73
+ );
74
+ }}
75
+ submitText="Book Now"
76
+ cancelText={null}
77
+ warnOnUnsavedChanges={false}
78
+ hideVisibilityInfo
79
+ />
80
+ </Card>
81
+ ),
82
+ },
83
+ ]}
84
+ />
85
+ </Card>
86
+ </div>
87
+ );
88
+ }
@@ -1,3 +1,5 @@
1
+ // apps/demo/src/pages/DashboardPage.tsx
2
+
1
3
  import { LayoutDashboard } from 'lucide-react';
2
4
 
3
5
  import { DashboardTemplate } from '@donotdev/templates';