create-lego-one 2.0.10 → 2.0.13

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 (242) hide show
  1. package/dist/index.cjs +179 -0
  2. package/dist/index.cjs.map +1 -1
  3. package/package.json +5 -3
  4. package/template/.cursor/rules/rules.mdc +639 -0
  5. package/template/.dockerignore +58 -0
  6. package/template/.env.example +18 -0
  7. package/template/.eslintignore +5 -0
  8. package/template/.eslintrc.js +28 -0
  9. package/template/.prettierignore +6 -0
  10. package/template/.prettierrc +11 -0
  11. package/template/CLAUDE.md +634 -0
  12. package/template/Dockerfile +67 -0
  13. package/template/PROMPT.md +457 -0
  14. package/template/README.md +325 -0
  15. package/template/docker-compose.yml +48 -0
  16. package/template/docker-entrypoint.sh +23 -0
  17. package/template/docs/checkpoints/.template.md +64 -0
  18. package/template/docs/checkpoints/framework/01-infrastructure-setup.md +132 -0
  19. package/template/docs/checkpoints/framework/02-pocketbase-setup.md +155 -0
  20. package/template/docs/checkpoints/framework/03-host-kernel.md +170 -0
  21. package/template/docs/checkpoints/framework/04-auth-system.md +163 -0
  22. package/template/docs/checkpoints/framework/phase-05-multitenancy-rbac.md +223 -0
  23. package/template/docs/checkpoints/framework/phase-06-ui-components.md +260 -0
  24. package/template/docs/checkpoints/framework/phase-07-communication-system.md +276 -0
  25. package/template/docs/checkpoints/framework/phase-08-plugin-system.md +91 -0
  26. package/template/docs/checkpoints/framework/phase-09-dashboard-plugin.md +111 -0
  27. package/template/docs/checkpoints/framework/phase-10-todo-plugin.md +169 -0
  28. package/template/docs/checkpoints/framework/phase-11-testing.md +264 -0
  29. package/template/docs/checkpoints/framework/phase-12-deployment.md +294 -0
  30. package/template/docs/checkpoints/framework/phase-13-documentation.md +312 -0
  31. package/template/docs/framework/plans/00-index.md +164 -0
  32. package/template/docs/framework/plans/01-infrastructure-setup.md +855 -0
  33. package/template/docs/framework/plans/02-pocketbase-setup.md +1374 -0
  34. package/template/docs/framework/plans/03-host-kernel.md +1518 -0
  35. package/template/docs/framework/plans/04-auth-system.md +1466 -0
  36. package/template/docs/framework/plans/05-multitenancy-rbac.md +1527 -0
  37. package/template/docs/framework/plans/06-ui-components.md +1478 -0
  38. package/template/docs/framework/plans/07-communication-system.md +1106 -0
  39. package/template/docs/framework/plans/08-plugin-system.md +1179 -0
  40. package/template/docs/framework/plans/09-dashboard-plugin.md +1137 -0
  41. package/template/docs/framework/plans/10-todo-plugin.md +1343 -0
  42. package/template/docs/framework/plans/11-testing.md +935 -0
  43. package/template/docs/framework/plans/12-deployment.md +896 -0
  44. package/template/docs/framework/prompts/0-boilerplate-modernjs.md +151 -0
  45. package/template/docs/framework/research/00-modernjs-audit.md +488 -0
  46. package/template/docs/framework/research/01-system-blueprint.md +721 -0
  47. package/template/docs/framework/research/02-data-migration-protocol.md +699 -0
  48. package/template/docs/framework/research/03-host-setup.md +714 -0
  49. package/template/docs/framework/research/04-plugin-architecture.md +645 -0
  50. package/template/docs/framework/research/05-slot-injection-pattern.md +671 -0
  51. package/template/docs/framework/research/06-cli-strategy.md +615 -0
  52. package/template/docs/framework/research/07-deployment.md +629 -0
  53. package/template/docs/framework/research/README.md +282 -0
  54. package/template/docs/framework/setup/00-index.md +210 -0
  55. package/template/docs/framework/setup/01-framework-structure.md +308 -0
  56. package/template/docs/framework/setup/02-development-workflow.md +405 -0
  57. package/template/docs/framework/setup/03-environment-setup.md +215 -0
  58. package/template/docs/framework/setup/04-kernel-architecture.md +499 -0
  59. package/template/docs/framework/setup/05-plugin-system.md +620 -0
  60. package/template/docs/framework/setup/06-communication-patterns.md +451 -0
  61. package/template/docs/framework/setup/07-plugin-development.md +582 -0
  62. package/template/docs/framework/setup/08-component-library.md +658 -0
  63. package/template/docs/framework/setup/09-data-integration.md +609 -0
  64. package/template/docs/framework/setup/10-auth-rbac.md +497 -0
  65. package/template/docs/framework/setup/11-hooks-api.md +393 -0
  66. package/template/docs/framework/setup/12-components-api.md +665 -0
  67. package/template/docs/framework/setup/13-deployment-guide.md +566 -0
  68. package/template/docs/framework/setup/README.md +548 -0
  69. package/template/host/e2e/auth.spec.ts +38 -0
  70. package/template/host/e2e/layout.spec.ts +38 -0
  71. package/template/host/modern.config.ts +19 -0
  72. package/template/host/package.json +71 -0
  73. package/template/host/playwright.config.ts +34 -0
  74. package/template/host/postcss.config.mjs +6 -0
  75. package/template/host/src/App.tsx +6 -0
  76. package/template/host/src/bootstrap.tsx +74 -0
  77. package/template/host/src/global.css +59 -0
  78. package/template/host/src/index.ts +2 -0
  79. package/template/host/src/kernel/__tests__/lib-utils.test.ts +32 -0
  80. package/template/host/src/kernel/__tests__/rbac-hooks.test.tsx +114 -0
  81. package/template/host/src/kernel/__tests__/rbac-utils.test.ts +108 -0
  82. package/template/host/src/kernel/auth/ProtectedRoute.tsx +41 -0
  83. package/template/host/src/kernel/auth/components/LoginForm.tsx +97 -0
  84. package/template/host/src/kernel/auth/components/LogoutButton.tsx +79 -0
  85. package/template/host/src/kernel/auth/hooks.ts +174 -0
  86. package/template/host/src/kernel/auth/index.ts +5 -0
  87. package/template/host/src/kernel/auth/schemas.ts +27 -0
  88. package/template/host/src/kernel/auth/service.ts +197 -0
  89. package/template/host/src/kernel/auth/types.ts +36 -0
  90. package/template/host/src/kernel/channels/ChannelBus.ts +181 -0
  91. package/template/host/src/kernel/channels/ChannelProvider.tsx +57 -0
  92. package/template/host/src/kernel/channels/events.ts +27 -0
  93. package/template/host/src/kernel/channels/hooks.ts +168 -0
  94. package/template/host/src/kernel/channels/index.ts +6 -0
  95. package/template/host/src/kernel/channels/integrations/ToastIntegration.tsx +60 -0
  96. package/template/host/src/kernel/channels/plugin-hooks.ts +72 -0
  97. package/template/host/src/kernel/channels/types.ts +112 -0
  98. package/template/host/src/kernel/components/__tests__/Badge.test.tsx +35 -0
  99. package/template/host/src/kernel/components/__tests__/Button.test.tsx +63 -0
  100. package/template/host/src/kernel/components/__tests__/Input.test.tsx +64 -0
  101. package/template/host/src/kernel/components/index.ts +32 -0
  102. package/template/host/src/kernel/components/ui/alert.tsx +58 -0
  103. package/template/host/src/kernel/components/ui/avatar.tsx +47 -0
  104. package/template/host/src/kernel/components/ui/badge.tsx +35 -0
  105. package/template/host/src/kernel/components/ui/button.tsx +50 -0
  106. package/template/host/src/kernel/components/ui/card.tsx +78 -0
  107. package/template/host/src/kernel/components/ui/dialog.tsx +116 -0
  108. package/template/host/src/kernel/components/ui/dropdown-menu.tsx +192 -0
  109. package/template/host/src/kernel/components/ui/index.ts +7 -0
  110. package/template/host/src/kernel/components/ui/input.tsx +24 -0
  111. package/template/host/src/kernel/components/ui/label.tsx +21 -0
  112. package/template/host/src/kernel/components/ui/popover.tsx +28 -0
  113. package/template/host/src/kernel/components/ui/progress.tsx +25 -0
  114. package/template/host/src/kernel/components/ui/scroll-area.tsx +45 -0
  115. package/template/host/src/kernel/components/ui/select.tsx +155 -0
  116. package/template/host/src/kernel/components/ui/separator.tsx +28 -0
  117. package/template/host/src/kernel/components/ui/skeleton.tsx +15 -0
  118. package/template/host/src/kernel/components/ui/switch.tsx +26 -0
  119. package/template/host/src/kernel/components/ui/table.tsx +116 -0
  120. package/template/host/src/kernel/components/ui/tabs.tsx +52 -0
  121. package/template/host/src/kernel/components/ui/toast.tsx +126 -0
  122. package/template/host/src/kernel/components/ui/toaster.tsx +34 -0
  123. package/template/host/src/kernel/components/ui/tooltip.tsx +27 -0
  124. package/template/host/src/kernel/components/ui/use-toast.ts +183 -0
  125. package/template/host/src/kernel/index.ts +48 -0
  126. package/template/host/src/kernel/lib/cn.ts +1 -0
  127. package/template/host/src/kernel/lib/utils.ts +36 -0
  128. package/template/host/src/kernel/plugins/Slot.tsx +41 -0
  129. package/template/host/src/kernel/plugins/SlotProvider.tsx +88 -0
  130. package/template/host/src/kernel/plugins/index.ts +23 -0
  131. package/template/host/src/kernel/plugins/loader.ts +122 -0
  132. package/template/host/src/kernel/plugins/schemas.ts +54 -0
  133. package/template/host/src/kernel/plugins/store.ts +185 -0
  134. package/template/host/src/kernel/plugins/types.ts +103 -0
  135. package/template/host/src/kernel/providers/PocketBaseProvider.tsx +70 -0
  136. package/template/host/src/kernel/providers/QueryProvider.tsx +28 -0
  137. package/template/host/src/kernel/providers/ThemeProvider.tsx +25 -0
  138. package/template/host/src/kernel/providers/index.ts +3 -0
  139. package/template/host/src/kernel/rbac/components/OrganizationSelector.tsx +69 -0
  140. package/template/host/src/kernel/rbac/components/PermissionGate.tsx +43 -0
  141. package/template/host/src/kernel/rbac/hooks.ts +379 -0
  142. package/template/host/src/kernel/rbac/index.ts +6 -0
  143. package/template/host/src/kernel/rbac/service.ts +504 -0
  144. package/template/host/src/kernel/rbac/types.ts +164 -0
  145. package/template/host/src/kernel/rbac/utils.ts +34 -0
  146. package/template/host/src/kernel/shared-state/bridge.ts +31 -0
  147. package/template/host/src/kernel/shared-state/index.ts +3 -0
  148. package/template/host/src/kernel/shared-state/store.ts +62 -0
  149. package/template/host/src/kernel/shared-state/types.ts +60 -0
  150. package/template/host/src/kernel/use-migrations.ts +72 -0
  151. package/template/host/src/layout/MobileMenu.tsx +61 -0
  152. package/template/host/src/layout/Shell.tsx +42 -0
  153. package/template/host/src/layout/Sidebar.tsx +178 -0
  154. package/template/host/src/layout/Topbar.tsx +50 -0
  155. package/template/host/src/layout/index.ts +4 -0
  156. package/template/host/src/lib/pocketbase/client.ts +38 -0
  157. package/template/host/src/lib/pocketbase/collections/audit_logs.ts +87 -0
  158. package/template/host/src/lib/pocketbase/collections/index.ts +19 -0
  159. package/template/host/src/lib/pocketbase/collections/organizations.ts +63 -0
  160. package/template/host/src/lib/pocketbase/collections/permissions.ts +57 -0
  161. package/template/host/src/lib/pocketbase/collections/roles.ts +55 -0
  162. package/template/host/src/lib/pocketbase/collections/todos.ts +74 -0
  163. package/template/host/src/lib/pocketbase/collections/user_roles.ts +57 -0
  164. package/template/host/src/lib/pocketbase/collections/users.ts +43 -0
  165. package/template/host/src/lib/pocketbase/index.ts +5 -0
  166. package/template/host/src/lib/pocketbase/migrations.ts +44 -0
  167. package/template/host/src/lib/pocketbase/seed/permissions.ts +8 -0
  168. package/template/host/src/lib/pocketbase/seed/roles.ts +22 -0
  169. package/template/host/src/lib/pocketbase/seed.ts +113 -0
  170. package/template/host/src/lib/pocketbase/types.ts +102 -0
  171. package/template/host/src/modern.runtime.ts +26 -0
  172. package/template/host/src/plugins.d.ts +9 -0
  173. package/template/host/src/providers/PocketBaseProvider.tsx +30 -0
  174. package/template/host/src/routes/_.tsx +6 -0
  175. package/template/host/src/routes/dashboard._.tsx +41 -0
  176. package/template/host/src/routes/index.tsx +93 -0
  177. package/template/host/src/routes/login.tsx +36 -0
  178. package/template/host/src/saas.config.ts +52 -0
  179. package/template/host/src/test/setup.ts +65 -0
  180. package/template/host/src/test/utils.tsx +69 -0
  181. package/template/host/src/test/vitest-globals.d.ts +19 -0
  182. package/template/host/src/vite-env.d.ts +16 -0
  183. package/template/host/tailwind.config.ts +77 -0
  184. package/template/host/tsconfig.json +19 -0
  185. package/template/host/vitest.config.ts +30 -0
  186. package/template/nginx.conf +72 -0
  187. package/template/package.json +44 -0
  188. package/template/packages/plugins/@lego/plugin-dashboard/modern.config.ts +19 -0
  189. package/template/packages/plugins/@lego/plugin-dashboard/package.json +35 -0
  190. package/template/packages/plugins/@lego/plugin-dashboard/postcss.config.mjs +6 -0
  191. package/template/packages/plugins/@lego/plugin-dashboard/src/App.tsx +27 -0
  192. package/template/packages/plugins/@lego/plugin-dashboard/src/components/ActivityFeed.tsx +63 -0
  193. package/template/packages/plugins/@lego/plugin-dashboard/src/components/QuickActionSlot.tsx +11 -0
  194. package/template/packages/plugins/@lego/plugin-dashboard/src/components/QuickActions.tsx +68 -0
  195. package/template/packages/plugins/@lego/plugin-dashboard/src/components/SidebarWidget.tsx +35 -0
  196. package/template/packages/plugins/@lego/plugin-dashboard/src/components/StatCard.tsx +47 -0
  197. package/template/packages/plugins/@lego/plugin-dashboard/src/global.css +24 -0
  198. package/template/packages/plugins/@lego/plugin-dashboard/src/hooks/useChannelIntegration.ts +43 -0
  199. package/template/packages/plugins/@lego/plugin-dashboard/src/hooks/useDashboardStats.ts +65 -0
  200. package/template/packages/plugins/@lego/plugin-dashboard/src/hooks/usePocketBase.ts +47 -0
  201. package/template/packages/plugins/@lego/plugin-dashboard/src/hooks/useRecentActivity.ts +55 -0
  202. package/template/packages/plugins/@lego/plugin-dashboard/src/lib/utils.ts +6 -0
  203. package/template/packages/plugins/@lego/plugin-dashboard/src/pages/DashboardPage.tsx +105 -0
  204. package/template/packages/plugins/@lego/plugin-dashboard/src/plugin.config.ts +121 -0
  205. package/template/packages/plugins/@lego/plugin-dashboard/src/plugin.ts +18 -0
  206. package/template/packages/plugins/@lego/plugin-dashboard/src/vite-env.d.ts +32 -0
  207. package/template/packages/plugins/@lego/plugin-dashboard/tailwind.config.ts +35 -0
  208. package/template/packages/plugins/@lego/plugin-dashboard/tsconfig.json +18 -0
  209. package/template/packages/plugins/@lego/plugin-todo/modern.config.ts +18 -0
  210. package/template/packages/plugins/@lego/plugin-todo/package.json +41 -0
  211. package/template/packages/plugins/@lego/plugin-todo/postcss.config.mjs +6 -0
  212. package/template/packages/plugins/@lego/plugin-todo/src/App.tsx +12 -0
  213. package/template/packages/plugins/@lego/plugin-todo/src/components/SidebarWidget.tsx +16 -0
  214. package/template/packages/plugins/@lego/plugin-todo/src/components/TodoDialog.tsx +55 -0
  215. package/template/packages/plugins/@lego/plugin-todo/src/components/TodoFilters.tsx +79 -0
  216. package/template/packages/plugins/@lego/plugin-todo/src/components/TodoForm.tsx +94 -0
  217. package/template/packages/plugins/@lego/plugin-todo/src/components/TodoItem.tsx +121 -0
  218. package/template/packages/plugins/@lego/plugin-todo/src/components/TodoList.tsx +41 -0
  219. package/template/packages/plugins/@lego/plugin-todo/src/components/index.ts +6 -0
  220. package/template/packages/plugins/@lego/plugin-todo/src/global.css +59 -0
  221. package/template/packages/plugins/@lego/plugin-todo/src/hooks/useCreateTodo.ts +62 -0
  222. package/template/packages/plugins/@lego/plugin-todo/src/hooks/useDeleteTodo.ts +46 -0
  223. package/template/packages/plugins/@lego/plugin-todo/src/hooks/usePocketBase.ts +38 -0
  224. package/template/packages/plugins/@lego/plugin-todo/src/hooks/useTodos.ts +64 -0
  225. package/template/packages/plugins/@lego/plugin-todo/src/hooks/useUpdateTodo.ts +35 -0
  226. package/template/packages/plugins/@lego/plugin-todo/src/index.tsx +5 -0
  227. package/template/packages/plugins/@lego/plugin-todo/src/lib/utils.ts +20 -0
  228. package/template/packages/plugins/@lego/plugin-todo/src/pages/TodoPage.tsx +89 -0
  229. package/template/packages/plugins/@lego/plugin-todo/src/plugin.config.ts +104 -0
  230. package/template/packages/plugins/@lego/plugin-todo/src/plugin.ts +13 -0
  231. package/template/packages/plugins/@lego/plugin-todo/src/schemas.ts +37 -0
  232. package/template/packages/plugins/@lego/plugin-todo/src/types.ts +42 -0
  233. package/template/packages/plugins/@lego/plugin-todo/src/vite-env.d.ts +31 -0
  234. package/template/packages/plugins/@lego/plugin-todo/tailwind.config.ts +51 -0
  235. package/template/packages/plugins/@lego/plugin-todo/tsconfig.json +18 -0
  236. package/template/pnpm-workspace.yaml +4 -0
  237. package/template/pocketbase/CHANGELOG.md +911 -0
  238. package/template/pocketbase/LICENSE.md +17 -0
  239. package/template/scripts/create-plugin.js +221 -0
  240. package/template/scripts/deploy.sh +56 -0
  241. package/template/tsconfig.base.json +26 -0
  242. package/template/tsconfig.json +8 -0
@@ -0,0 +1,615 @@
1
+ # CLI Strategy: Project Scaffolding
2
+
3
+ **Project:** Lego-One (Modern.js SaaS OS)
4
+ **Document:** 06 - CLI Strategy
5
+ **Status:** Research Phase
6
+
7
+ ## Executive Summary
8
+
9
+ This document explains how to implement the `pnpm create lego-one` command that allows developers to scaffold a new Lego-One project. Since we're using the **Git Template** approach, the CLI will be a lightweight wrapper around git operations and project configuration.
10
+
11
+ ---
12
+
13
+ ## 1. CLI Overview
14
+
15
+ ### 1.1 Command Structure
16
+
17
+ ```bash
18
+ # Create new project from template
19
+ pnpm create lego-one my-saas-app
20
+
21
+ # With interactive prompts
22
+ pnpm create lego-one my-saas-app --interactive
23
+
24
+ # Skip git initialization
25
+ pnpm create lego-one my-saas-app --no-git
26
+
27
+ # Use specific branch
28
+ pnpm create lego-one my-saas-app --branch v2.0.0
29
+ ```
30
+
31
+ ### 1.2 What the CLI Does
32
+
33
+ 1. **Clone Template:** Fetches lego-one from GitHub
34
+ 2. **Configure:** Updates package.json, env vars
35
+ 3. **Install:** Runs `pnpm install`
36
+ 4. **Initialize Git:** Creates initial commit
37
+ 5. **Configure Plugins:** Prompts for which plugins to enable
38
+
39
+ ---
40
+
41
+ ## 2. Implementation Options
42
+
43
+ ### 2.1 Option A: npm create (Recommended)
44
+
45
+ Uses npm's built-in `create-*` command pattern.
46
+
47
+ **Entry Point:** `packages/create-lego-one/package.json`
48
+
49
+ ```json
50
+ {
51
+ "name": "create-lego-one",
52
+ "version": "1.0.0",
53
+ "bin": "./dist/index.js",
54
+ "files": ["dist"],
55
+ "scripts": {
56
+ "build": "tsup src/index.ts --format cjs --clean",
57
+ "dev": "tsup src/index.ts --format cjs --watch"
58
+ },
59
+ "dependencies": {
60
+ "prompts": "^2.4.2",
61
+ "commander": "^12.0.0",
62
+ "chalk": "^5.3.0",
63
+ "ora": "^8.0.1",
64
+ "fs-extra": "^11.2.0",
65
+ "execa": "^8.0.1"
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### 2.2 Option B: Global CLI
71
+
72
+ Install globally and run as a command:
73
+
74
+ ```bash
75
+ pnpm add -g @lego/cli
76
+ lego-one create my-saas-app
77
+ ```
78
+
79
+ ### 2.3 Option C: npx (Simplest)
80
+
81
+ No package needed - uses a template repo directly:
82
+
83
+ ```bash
84
+ npx create-lego-one@latest my-saas-app
85
+ ```
86
+
87
+ **Our Choice:** Option A (npm create) - standard pattern, good DX.
88
+
89
+ ---
90
+
91
+ ## 3. CLI Implementation
92
+
93
+ ### 3.1 Main Entry Point
94
+
95
+ **File:** `packages/create-lego-one/src/index.ts`
96
+
97
+ ```typescript
98
+ #!/usr/bin/env node
99
+
100
+ import { Command } from 'commander';
101
+ import chalk from 'chalk';
102
+ import { createProject } from './commands/create';
103
+ import { addPlugin } from './commands/add-plugin';
104
+
105
+ const program = new Command();
106
+
107
+ program
108
+ .name('create-lego-one')
109
+ .description('Create a new Lego-One SaaS application')
110
+ .version('1.0.0');
111
+
112
+ program
113
+ .argument('[project-name]', 'Name of the project')
114
+ .option('-i, --interactive', 'Use interactive mode')
115
+ .option('--no-git', 'Skip git initialization')
116
+ .option('--branch <branch>', 'Template branch to use', 'main')
117
+ .action(async (projectName, options) => {
118
+ try {
119
+ await createProject(projectName, options);
120
+ } catch (error) {
121
+ console.error(chalk.red('Error:'), error.message);
122
+ process.exit(1);
123
+ }
124
+ });
125
+
126
+ program
127
+ .command('add-plugin <plugin-name>')
128
+ .description('Add a plugin to the current project')
129
+ .action(addPlugin);
130
+
131
+ program.parse();
132
+ ```
133
+
134
+ ### 3.2 Create Project Command
135
+
136
+ **File:** `packages/create-lego-one/src/commands/create.ts`
137
+
138
+ ```typescript
139
+ import path from 'path';
140
+ import fs from 'fs-extra';
141
+ import chalk from 'chalk';
142
+ import ora from 'ora';
143
+ import prompts from 'prompts';
144
+ import { execaCommand } from 'execa';
145
+
146
+ interface CreateOptions {
147
+ interactive?: boolean;
148
+ git?: boolean;
149
+ branch?: string;
150
+ }
151
+
152
+ export async function createProject(
153
+ projectName: string | undefined,
154
+ options: CreateOptions
155
+ ) {
156
+ const spinner = ora();
157
+
158
+ // Interactive mode or get project name
159
+ let name = projectName;
160
+ let targetDir = process.cwd();
161
+
162
+ if (options.interactive || !name) {
163
+ const response = await prompts([
164
+ {
165
+ type: 'text',
166
+ name: 'name',
167
+ message: 'Project name:',
168
+ initial: 'my-saas-app',
169
+ validate: (n) => /^[a-z0-9-]+$/.test(n) || 'Only lowercase, numbers, and hyphens allowed',
170
+ },
171
+ {
172
+ type: 'select',
173
+ name: 'location',
174
+ message: 'Where to create the project?',
175
+ choices: [
176
+ { title: 'Current directory', value: 'current' },
177
+ { title: 'New subdirectory', value: 'subdirectory' },
178
+ ],
179
+ initial: 0,
180
+ },
181
+ ]);
182
+
183
+ name = response.name;
184
+ if (response.location === 'subdirectory') {
185
+ targetDir = path.join(targetDir, name);
186
+ }
187
+ }
188
+
189
+ if (!name) {
190
+ throw new Error('Project name is required');
191
+ }
192
+
193
+ const templateRepo = 'https://github.com/lego-one/lego-one.git';
194
+ const tempDir = path.join(targetDir, '.template-temp');
195
+
196
+ // Step 1: Clone template
197
+ spinner.start('Cloning Lego-One template...');
198
+ try {
199
+ await execaCommand(
200
+ `git clone --depth 1 --branch ${options.branch} ${templateRepo} ${tempDir}`
201
+ );
202
+ spinner.succeed('Template cloned');
203
+ } catch (error) {
204
+ spinner.fail('Failed to clone template');
205
+ throw error;
206
+ }
207
+
208
+ // Step 2: Copy files to target
209
+ spinner.start('Setting up project files...');
210
+ try {
211
+ // Copy all files except .git
212
+ const files = await fs.readdir(tempDir);
213
+ for (const file of files) {
214
+ if (file !== '.git') {
215
+ await fs.copy(
216
+ path.join(tempDir, file),
217
+ path.join(targetDir, file),
218
+ { overwrite: true }
219
+ );
220
+ }
221
+ }
222
+
223
+ // Remove temp directory
224
+ await fs.remove(tempDir);
225
+ spinner.succeed('Project files created');
226
+ } catch (error) {
227
+ spinner.fail('Failed to copy files');
228
+ throw error;
229
+ }
230
+
231
+ // Step 3: Configure package.json
232
+ spinner.start('Configuring project...');
233
+ try {
234
+ const packageJsonPath = path.join(targetDir, 'package.json');
235
+ const packageJson = await fs.readJson(packageJsonPath);
236
+
237
+ // Update project name
238
+ packageJson.name = name;
239
+
240
+ // Remove private flag (user may want to publish)
241
+ delete packageJson.private;
242
+
243
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
244
+ spinner.succeed('Project configured');
245
+ } catch (error) {
246
+ spinner.fail('Failed to configure project');
247
+ throw error;
248
+ }
249
+
250
+ // Step 4: Interactive plugin selection
251
+ if (options.interactive) {
252
+ const { plugins } = await prompts({
253
+ type: 'multiselect',
254
+ name: 'plugins',
255
+ message: 'Select plugins to enable:',
256
+ choices: [
257
+ { title: 'Dashboard', value: '@lego/plugin-dashboard', selected: true },
258
+ { title: 'Auth', value: '@lego/plugin-auth', selected: true },
259
+ { title: 'Billing (Stripe)', value: '@lego/plugin-billing' },
260
+ { title: 'Inventory', value: '@lego/plugin-inventory' },
261
+ { title: 'Loan Calculator', value: '@lego/plugin-loan-calculator' },
262
+ ],
263
+ });
264
+
265
+ // Update saas.config.ts
266
+ await updateSaaSConfig(targetDir, plugins);
267
+ }
268
+
269
+ // Step 5: Install dependencies
270
+ spinner.start('Installing dependencies...');
271
+ try {
272
+ await execaCommand('pnpm install', { cwd: targetDir });
273
+ spinner.succeed('Dependencies installed');
274
+ } catch (error) {
275
+ spinner.warn('Failed to install dependencies. Run `pnpm install` manually.');
276
+ }
277
+
278
+ // Step 6: Git initialization
279
+ if (options.git !== false) {
280
+ spinner.start('Initializing git...');
281
+ try {
282
+ await execaCommand('git init', { cwd: targetDir });
283
+ await execaCommand('git add .', { cwd: targetDir });
284
+ await execaCommand('git commit -m "Initial commit from Lego-One"', {
285
+ cwd: targetDir,
286
+ });
287
+ spinner.succeed('Git initialized');
288
+ } catch (error) {
289
+ spinner.warn('Git initialization failed');
290
+ }
291
+ }
292
+
293
+ // Success message
294
+ console.log('\n' + chalk.green('✓ Project created successfully!\n'));
295
+ console.log(chalk.cyan('Next steps:\n'));
296
+ console.log(` cd ${name}`);
297
+ console.log(' pnpm run dev');
298
+ console.log('\n' + chalk.gray('Happy building!'));
299
+ }
300
+
301
+ async function updateSaaSConfig(targetDir: string, enabledPlugins: string[]) {
302
+ const configPath = path.join(targetDir, 'saas.config.ts');
303
+
304
+ let configContent = await fs.readFile(configPath, 'utf-8');
305
+
306
+ // Update enabled plugins
307
+ const pluginsSection = enabledPlugins
308
+ .map((p) => ` { name: '${p}', enabled: true }`)
309
+ .join(',\n');
310
+
311
+ configContent = configContent.replace(
312
+ /plugins: \[[\s\S]*?\]/,
313
+ `plugins: [\n${pluginsSection}\n ]`
314
+ );
315
+
316
+ await fs.writeFile(configPath, configContent);
317
+ }
318
+ ```
319
+
320
+ ### 3.3 Add Plugin Command
321
+
322
+ **File:** `packages/create-lego-one/src/commands/add-plugin.ts`
323
+
324
+ ```typescript
325
+ import path from 'path';
326
+ import fs from 'fs-extra';
327
+ import chalk from 'chalk';
328
+ import ora from 'ora';
329
+
330
+ export async function addPlugin(pluginName: string) {
331
+ const spinner = ora();
332
+ const projectRoot = process.cwd();
333
+
334
+ // Check if we're in a Lego-One project
335
+ const packageJsonPath = path.join(projectRoot, 'package.json');
336
+ if (!fs.existsSync(packageJsonPath)) {
337
+ throw new Error('Not in a valid project directory');
338
+ }
339
+
340
+ const packageJson = await fs.readJson(packageJsonPath);
341
+ if (!packageJson.name?.startsWith('lego-one')) {
342
+ throw new Error('Not a Lego-One project');
343
+ }
344
+
345
+ spinner.start(`Adding plugin: ${pluginName}...`);
346
+
347
+ try {
348
+ // Update saas.config.ts
349
+ const configPath = path.join(projectRoot, 'saas.config.ts');
350
+ let configContent = await fs.readFile(configPath, 'utf-8');
351
+
352
+ // Add plugin to the list
353
+ const pluginEntry = ` { name: '${pluginName}', enabled: true }`;
354
+
355
+ if (configContent.includes('plugins: [')) {
356
+ configContent = configContent.replace(
357
+ 'plugins: [',
358
+ `plugins: [\n${pluginEntry},`
359
+ );
360
+ }
361
+
362
+ await fs.writeFile(configPath, configContent);
363
+
364
+ spinner.succeed(`Plugin ${pluginName} added`);
365
+ console.log('\n' + chalk.gray('Update modern.runtime.ts to add the sub-app entry.'));
366
+ } catch (error) {
367
+ spinner.fail(`Failed to add plugin: ${error.message}`);
368
+ throw error;
369
+ }
370
+ }
371
+ ```
372
+
373
+ ---
374
+
375
+ ## 4. Template Repository Structure
376
+
377
+ ### 4.1 GitHub Template Setup
378
+
379
+ **Repository:** `github.com/lego-one/lego-one`
380
+
381
+ ```
382
+ lego-one/ # Template repository
383
+ ├── .github/
384
+ │ └── workflows/
385
+ │ └── template-sync.yml # Sync upstream changes
386
+ ├── host/
387
+ │ ├── src/
388
+ │ ├── modern.config.ts
389
+ │ └── package.json
390
+ ├── packages/
391
+ │ └── plugins/
392
+ │ └── @lego/
393
+ │ ├── plugin-dashboard/
394
+ │ ├── plugin-auth/
395
+ │ └── plugin-billing/
396
+ ├── saas.config.ts # User-editable config
397
+ ├── pnpm-workspace.yaml
398
+ ├── package.json # Root package.json
399
+ ├── README.md
400
+ └── .gitignore
401
+ ```
402
+
403
+ ### 4.2 Template Configuration
404
+
405
+ **File:** `lego-one/.github/template-config.yml`
406
+
407
+ ```yaml
408
+ # Template repository configuration
409
+ name: Lego-One SaaS OS
410
+ description: Microkernel SaaS boilerplate with Modern.js
411
+
412
+ # Files to exclude when using as template
413
+ exclude:
414
+ - .git/
415
+ - node_modules/
416
+ - dist/
417
+ - .env.local
418
+ - pnpm-lock.yaml
419
+
420
+ # Prompts for users
421
+ prompts:
422
+ - id: project_name
423
+ name: Project Name
424
+ default: my-saas-app
425
+ - id: pocketbase_url
426
+ name: PocketBase URL
427
+ default: http://localhost:8090
428
+ - id: enable_dashboard
429
+ name: Enable Dashboard Plugin
430
+ type: boolean
431
+ default: true
432
+ - id: enable_auth
433
+ name: Enable Auth Plugin
434
+ type: boolean
435
+ default: true
436
+ ```
437
+
438
+ ---
439
+
440
+ ## 5. Publishing the CLI
441
+
442
+ ### 5.1 Package.json
443
+
444
+ **File:** `packages/create-lego-one/package.json`
445
+
446
+ ```json
447
+ {
448
+ "name": "create-lego-one",
449
+ "version": "1.0.0",
450
+ "description": "Create a new Lego-One SaaS application",
451
+ "bin": "./dist/index.js",
452
+ "files": ["dist"],
453
+ "scripts": {
454
+ "build": "tsup src/index.ts --format cjs --clean",
455
+ "dev": "tsup src/index.ts --format cjs --watch",
456
+ "prepublishOnly": "pnpm run build"
457
+ },
458
+ "keywords": [
459
+ "create-app",
460
+ "lego-one",
461
+ "saas",
462
+ "micro-frontend",
463
+ "modernjs"
464
+ ],
465
+ "exports": "./dist/index.js",
466
+ "repository": {
467
+ "type": "git",
468
+ "url": "https://github.com/lego-one/create-lego-one.git"
469
+ },
470
+ "dependencies": {
471
+ "commander": "^12.0.0",
472
+ "chalk": "^5.3.0",
473
+ "ora": "^8.0.1",
474
+ "prompts": "^2.4.2",
475
+ "execa": "^8.0.1",
476
+ "fs-extra": "^11.2.0"
477
+ },
478
+ "devDependencies": {
479
+ "@types/node": "^20.11.0",
480
+ "@types/prompts": "^2.4.9",
481
+ "@types/fs-extra": "^11.0.4",
482
+ "tsup": "^8.0.0",
483
+ "typescript": "^5.3.0"
484
+ },
485
+ "engines": {
486
+ "node": ">=18.0.0",
487
+ "pnpm": ">=8.0.0"
488
+ }
489
+ }
490
+ ```
491
+
492
+ ### 5.2 Build Configuration
493
+
494
+ **File:** `packages/create-lego-one/tsup.config.ts`
495
+
496
+ ```typescript
497
+ import { defineConfig } from 'tsup';
498
+
499
+ export default defineConfig({
500
+ entry: ['src/index.ts'],
501
+ format: ['cjs'],
502
+ target: 'node18',
503
+ clean: true,
504
+ shims: true,
505
+ banner: {
506
+ js: '#!/usr/bin/env node',
507
+ },
508
+ });
509
+ ```
510
+
511
+ ### 5.3 Publish to npm
512
+
513
+ ```bash
514
+ # Build the CLI
515
+ cd packages/create-lego-one
516
+ pnpm run build
517
+
518
+ # Publish to npm
519
+ pnpm publish --access public
520
+ ```
521
+
522
+ ---
523
+
524
+ ## 6. User Experience
525
+
526
+ ### 6.1 Creating a New Project
527
+
528
+ ```bash
529
+ # User runs:
530
+ pnpm create lego-one my-saas-app
531
+
532
+ # Output:
533
+ ✓ Cloning Lego-One template...
534
+ ✓ Setting up project files...
535
+ ✓ Configuring project...
536
+ ✓ Installing dependencies...
537
+ ✓ Git initialized
538
+
539
+ ✓ Project created successfully!
540
+
541
+ Next steps:
542
+ cd my-saas-app
543
+ pnpm run dev
544
+
545
+ Happy building!
546
+ ```
547
+
548
+ ### 6.2 Interactive Mode
549
+
550
+ ```bash
551
+ pnpm create lego-one --interactive
552
+
553
+ # Prompts:
554
+ ? Project name: my-saas-app
555
+ ? Where to create the project? Current directory
556
+ ? Select plugins to enable:
557
+ ✓ Dashboard
558
+ ✓ Auth
559
+ ○ Billing (Stripe)
560
+ ○ Inventory
561
+ ○ Loan Calculator
562
+
563
+ # ... creates project with selected plugins enabled
564
+ ```
565
+
566
+ ---
567
+
568
+ ## 7. Update Workflow
569
+
570
+ ### 7.1 User Updates from Template
571
+
572
+ Since we're using Git Template approach:
573
+
574
+ ```bash
575
+ # In user's project
576
+ git remote add upstream https://github.com/lego-one/lego-one.git
577
+ git fetch upstream
578
+ git merge upstream/main
579
+
580
+ # Resolve conflicts as needed
581
+ # The user keeps their custom plugins in separate branch or subtree
582
+ ```
583
+
584
+ ### 7.2 Plugin Updates
585
+
586
+ Official plugins are managed via git subtree/submodule:
587
+
588
+ ```bash
589
+ # Add official plugin as subtree
590
+ git subtree add \
591
+ --prefix=packages/plugins/@lego/plugin-dashboard \
592
+ https://github.com/lego-one/plugin-dashboard.git \
593
+ main
594
+
595
+ # Update plugin later
596
+ git subtree pull \
597
+ --prefix=packages/plugins/@lego/plugin-dashboard \
598
+ https://github.com/lego-one/plugin-dashboard.git \
599
+ main
600
+ ```
601
+
602
+ ---
603
+
604
+ ## 8. Next Steps
605
+
606
+ 1. **`07-deployment.md`**: Deploy host and plugins to production
607
+
608
+ ---
609
+
610
+ ## References
611
+
612
+ - [npm create Documentation](https://docs.npmjs.com/cli/v9/commands/npm-create)
613
+ - [Commander.js](https://commander.js.org/)
614
+ - [GitHub Template Repositories](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository)
615
+ - [pnpm Workspace](https://pnpm.io/workspaces)