create-lego-one 2.0.12 → 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 (78) hide show
  1. package/dist/index.cjs +34 -0
  2. package/dist/index.cjs.map +1 -1
  3. package/package.json +1 -1
  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/package.json +1 -1
  70. package/template/nginx.conf +72 -0
  71. package/template/package.json +1 -1
  72. package/template/packages/plugins/@lego/plugin-dashboard/package.json +1 -1
  73. package/template/packages/plugins/@lego/plugin-todo/package.json +1 -1
  74. package/template/pocketbase/CHANGELOG.md +911 -0
  75. package/template/pocketbase/LICENSE.md +17 -0
  76. package/template/scripts/create-plugin.js +221 -0
  77. package/template/scripts/deploy.sh +56 -0
  78. package/template/tsconfig.base.json +26 -0
@@ -0,0 +1,151 @@
1
+ # **Project: Lego-One (The Modern.js SaaS OS)**
2
+
3
+ **Role:** You are an elite **Software Architect** specializing in the **Modern.js Ecosystem (ByteDance)**, Micro-Frontends (Garfish), and Scalable SaaS Infrastructure.
4
+
5
+ **Objective:** Create a comprehensive, production-ready architectural blueprint for a modular "All-in-One" SaaS Boilerplate (internal code name: **lego-one**).
6
+
7
+ **The Core Vision:** This is a **Microkernel Operating System** for SaaS. It separates **Core Infrastructure** (Kernel) from **Business Logic** (Plugins).
8
+
9
+ * **The Difference:** Unlike a standard Monolith, we are using **Modern.js** to natively handle Micro-Frontends. The Kernel shouldn't just "import" components; it should load them as independent sub-apps or modules where possible, while keeping a unified developer experience.
10
+
11
+ ---
12
+
13
+ ### **1. The Tech Stack (Strict Adherence)**
14
+
15
+ * **Host Framework:** **Modern.js** (Framework)
16
+ * *Configuration:* Must use the **Rspack** bundler for performance.
17
+ * *Mode:* Enable **Micro-Frontend (MFE)** mode natively.
18
+
19
+
20
+ * **Micro-Frontend Engine:** **Garfish** (Built-in to Modern.js).
21
+ * **Language:** TypeScript (Strict Mode).
22
+ * **Backend/Database:** PocketBase.
23
+ * *Constraint:* Use PocketBase **API Rules** for strict Multi-tenancy (Row Level Security).
24
+
25
+
26
+ * **State Management:**
27
+ * **Global UI:** Zustand (Shared across Host and Plugins).
28
+ * **Server State:** TanStack Query v5.
29
+
30
+
31
+ * **UI System:** Tailwind CSS, Shadcn UI, Radix Primitives.
32
+ * *Note:* Since Shadcn is optimized for Next.js, you must document the specific `postcss`/`tailwind.config.js` setup required to make it work seamlessly in Modern.js.
33
+
34
+
35
+
36
+ ---
37
+
38
+ ### **2. Architecture & Functional Requirements**
39
+
40
+ #### **A. The "Kernel" vs. "Userland" Structure**
41
+
42
+ * **The Kernel (Host App):**
43
+ * Handles Authentication (Login/Register).
44
+ * Manages the Global Layout (Sidebar, Topbar, Toasts).
45
+ * Loads the `saas.config.ts` to determine which Plugins to fetch.
46
+
47
+
48
+ * **The Plugins (Sub-Apps):**
49
+ * **Feature Plugins:** Standalone Modern.js sub-apps (e.g., "Loan Calculator"). They expose specific routes and UI components.
50
+ * **Integration Plugins:** "Drivers" for 3rd party tools (e.g., Stripe, Snowflake).
51
+
52
+
53
+ * **Communication:**
54
+ * Define the **Bus System**: How does a Sub-App (Plugin) trigger a Toast in the Host App? How does the Host pass the `currentUser` object to the Sub-App?
55
+
56
+
57
+
58
+ #### **B. The "Update Paradox" (Boilerplate vs. NPM)**
59
+
60
+ We need to update the Core without breaking the User's custom plugins.
61
+
62
+ * **Requirement:** Define the update strategy.
63
+ * *Scenario:* A developer starts their project. Two months later, we release `lego-one v2.0` with a new Auth interface.
64
+ * *Question:* Should `lego-one` be an **NPM Dependency** (imported by the host) or a **Git Template**?
65
+ * *Constraint:* Favor an approach where the "Kernel" logic is abstracted as much as possible so updates are painless.
66
+
67
+
68
+
69
+ #### **C. The "Migration Protocol" (PocketBase)**
70
+
71
+ * **Problem:** PocketBase doesn't have standard SQL migrations for plugins.
72
+ * **Requirement:** Design a startup protocol. When the Host App boots:
73
+ 1. It reads `saas.config.ts`.
74
+ 2. It detects enabled plugins (e.g., `@lego/plugin-inventory`).
75
+ 3. It executes a "Schema Check" against the PocketBase API to ensure the `inventory` collection exists. If not, it creates it programmatically using the Admin API.
76
+
77
+
78
+
79
+ #### **D. UI Slot Injection**
80
+
81
+ * **Requirement:** Plugins must be able to inject UI into the Host Layout *outside* of their own routes.
82
+ * *Example:* The "Stripe Plugin" is active. It needs to inject a "Billing" link into the **Host's Sidebar** and a "Credit Balance" badge into the **Host's Topbar**.
83
+ * *Task:* Explain how to achieve this using Modern.js/Garfish props or a global "Slot Registry."
84
+
85
+
86
+
87
+ ---
88
+
89
+ ### **3. UI/UX Visualization**
90
+
91
+ The app functions as a "Shell". Use this reference for your planning:
92
+
93
+ ```mermaid
94
+ graph TD
95
+ subgraph Browser_Window ["Browser Window"]
96
+ direction TB
97
+ Shell[Modern.js Host (Kernel)]
98
+
99
+ subgraph Host_UI ["Host UI"]
100
+ Sidebar[Sidebar Nav]
101
+ TopBar[Top Bar]
102
+ Toasts[Sonner Toasts]
103
+ end
104
+
105
+ subgraph Content_Area ["Garfish Router Outlet"]
106
+ direction LR
107
+ Dashboard[Dashboard Page]
108
+ PluginA[Sub-App: Loan Calc]
109
+ PluginB[Sub-App: Inventory]
110
+ Settings[Admin Settings]
111
+ end
112
+ end
113
+
114
+ %% Slot Injection Logic
115
+ PluginA -.-> |"Injects Link"| Sidebar
116
+ PluginB -.-> |"Injects Badge"| TopBar
117
+
118
+ %% Routing
119
+ Sidebar -- "/dashboard" --> Dashboard
120
+ Sidebar -- "/apps/loan" --> PluginA
121
+
122
+ ```
123
+
124
+ ---
125
+
126
+ ### **4. Deliverables & Documentation Structure**
127
+
128
+ You are required to perform deep analysis. **Do not output a single file.** Generate a comprehensive documentation set. Use the following file structure as your checklist.
129
+
130
+ **Phase 0: Architecture & Research**
131
+
132
+ * `docs/research/00-modernjs-audit.md`: **Validate the config.** Confirm exactly how `modern.config.ts` should be set up for the Host vs. the Sub-apps. Address how **Shared Dependencies** (React, Zustand) are handled to prevent double-loading.
133
+ * `docs/research/01-system-blueprint.md`: The high-level diagram of the Host/Consumer relationship.
134
+ * `docs/research/02-data-migration-protocol.md`: The technical design for the PocketBase auto-schema script.
135
+
136
+ **Phase 1: Implementation Plan**
137
+
138
+ * `docs/research/03-host-setup.md`: Steps to initialize the Modern.js Host App with Tailwind/Shadcn.
139
+ * `docs/research/04-plugin-architecture.md`: How to create a "Hello World" plugin and register it in the Host.
140
+ * `docs/research/05-slot-injection-pattern.md`: The code pattern for allowing plugins to inject items into the Sidebar/Topbar.
141
+
142
+ **Phase 2: DevOps**
143
+
144
+ * `docs/research/06-cli-strategy.md`: How the `pnpm create` command works.
145
+ * `docs/research/07-deployment.md`: How to deploy the Host and Sub-apps (Monorepo vs Polyrepo strategy).
146
+
147
+ **Instructions for the Output:**
148
+
149
+ 1. **Start with `docs/research/00-modernjs-audit.md**`. I need to see the `modern.config.ts` strategy first.
150
+ 2. Be technical. Use specific API names (e.g., `garfish.loadApp`, `runtime.useModule`).
151
+ 3. Solve the **Sharing Problem**: How do we share `zustand` state between the Host and the Micro-frontend Plugin?
@@ -0,0 +1,488 @@
1
+ # Modern.js Configuration Audit
2
+
3
+ **Project:** Lego-One (Modern.js SaaS OS)
4
+ **Document:** 00 - Modern.js Configuration Strategy
5
+ **Status:** Research Phase
6
+
7
+ ## Executive Summary
8
+
9
+ This document validates the `modern.config.ts` configuration strategy for the Lego-One Microkernel architecture using Modern.js with Garfish micro-frontend support and Rspack bundler.
10
+
11
+ ---
12
+
13
+ ## 1. Host App Configuration (The "Kernel")
14
+
15
+ ### 1.1 Base Configuration
16
+
17
+ **File:** `host/modern.config.ts`
18
+
19
+ ```typescript
20
+ import { appTools, defineConfig } from '@modern-js/app-tools';
21
+ import { garfishPlugin } from '@modern-js/plugin-garfish';
22
+
23
+ export default defineConfig({
24
+ // Enable Rspack for high-performance builds
25
+ tools: {
26
+ rspack: (config, { appendPlugins }) => {
27
+ // Rspack is enabled by default in Modern.js v2+
28
+ return config;
29
+ },
30
+ },
31
+
32
+ // Enable file-based routing for the host kernel
33
+ runtime: {
34
+ router: true,
35
+ },
36
+
37
+ // Register Garfish plugin for micro-frontend capabilities
38
+ plugins: [appTools(), garfishPlugin()],
39
+ });
40
+ ```
41
+
42
+ ### 1.2 Runtime Configuration
43
+
44
+ **File:** `host/src/modern.runtime.ts`
45
+
46
+ ```typescript
47
+ import { defineRuntimeConfig } from '@modern-js/runtime';
48
+
49
+ // Development vs Production configuration
50
+ const isDev = import.meta.env.MODE === 'development';
51
+
52
+ export default defineRuntimeConfig({
53
+ masterApp: {
54
+ apps: [
55
+ {
56
+ name: '@lego/plugin-dashboard',
57
+ // Dev: Separate server │ Prod: Bundled via dynamic import
58
+ entry: isDev
59
+ ? 'http://localhost:3001'
60
+ : () => import('@lego/plugin-dashboard'),
61
+ activeWhen: '/dashboard',
62
+ },
63
+ {
64
+ name: '@lego/plugin-loan-calculator',
65
+ entry: isDev
66
+ ? 'http://localhost:3002'
67
+ : () => import('@lego/plugin-loan-calculator'),
68
+ activeWhen: '/apps/loan',
69
+ },
70
+ {
71
+ name: '@lego/plugin-inventory',
72
+ entry: isDev
73
+ ? 'http://localhost:3003'
74
+ : () => import('@lego/plugin-inventory'),
75
+ activeWhen: '/apps/inventory',
76
+ },
77
+ ],
78
+ },
79
+ });
80
+ ```
81
+
82
+ **Key Configuration Points:**
83
+ - `activeWhen`: Defines the route prefix that triggers each sub-app load
84
+ - `entry` (Development): URL to separate dev server (e.g., `http://localhost:3001`)
85
+ - `entry` (Production): Dynamic import function - Modern.js bundles plugin into host
86
+ - Apps are loaded dynamically based on route matching
87
+
88
+ **Development Workflow:**
89
+ ```bash
90
+ # Terminal 1: Host
91
+ cd host && pnpm run dev # :8080
92
+
93
+ # Terminal 2: Plugin (optional, for independent development)
94
+ cd packages/plugins/@lego/plugin-dashboard && pnpm run dev # :3001
95
+ ```
96
+
97
+ **Production:**
98
+ ```bash
99
+ # Single build bundles everything
100
+ pnpm run build
101
+
102
+ # Deploy host/dist/ only - plugins are already bundled inside!
103
+ ```
104
+
105
+ ### 1.3 Shared Dependencies Configuration
106
+
107
+ **File:** `host/src/bootstrap.tsx` (or in `App.tsx` / `main.tsx`)
108
+
109
+ ```typescript
110
+ import React from 'react';
111
+ import ReactDOM from 'react-dom';
112
+ import { create } from 'zustand';
113
+ import Garfish from 'garfish';
114
+
115
+ // Initialize Zustand store for shared global state
116
+ export const useGlobalStore = create((set) => ({
117
+ currentUser: null,
118
+ setCurrentUser: (user) => set({ currentUser: user }),
119
+ theme: 'light',
120
+ setTheme: (theme) => set({ theme }),
121
+ }));
122
+
123
+ // Register shared dependencies via Garfish.setExternal
124
+ // This allows sub-apps to use the same React, ReactDOM, and Zustand instances
125
+ Garfish.setExternal({
126
+ react: React,
127
+ 'react-dom': ReactDOM,
128
+ '@lego/kernel-state': {
129
+ useGlobalStore,
130
+ },
131
+ });
132
+ ```
133
+
134
+ **IMPORTANT:** Garfish externals configuration is handled differently in Modern.js. The `@modern-js/plugin-garfish` automatically handles shared dependencies through Modern.js's Module Federation layer. The `Garfish.setExternal` call above is for **application-level state sharing** (Zustand store), not framework dependencies.
135
+
136
+ ---
137
+
138
+ ## 2. Sub-App (Plugin) Configuration
139
+
140
+ ### 2.1 Base Plugin Configuration
141
+
142
+ **File:** `plugins/@lego/plugin-loan-calculator/modern.config.ts`
143
+
144
+ ```typescript
145
+ import { appTools, defineConfig } from '@modern-js/app-tools';
146
+ import { garfishPlugin } from '@modern-js/plugin-garfish';
147
+
148
+ export default defineConfig({
149
+ dev: {
150
+ port: 3002, // Each plugin gets its own dev port
151
+ },
152
+
153
+ runtime: {
154
+ router: true,
155
+ },
156
+
157
+ // CRITICAL: Mark this as a micro-frontend sub-app
158
+ deploy: {
159
+ microFrontend: true,
160
+ },
161
+
162
+ plugins: [appTools(), garfishPlugin()],
163
+ });
164
+ ```
165
+
166
+ ### 2.2 Plugin Entry Point
167
+
168
+ **File:** `plugins/@lego/plugin-loan-calculator/src/App.tsx`
169
+
170
+ ```typescript
171
+ import { BrowserRouter, Routes, Route } from '@modern-js/runtime/router';
172
+
173
+ // The basename prop is automatically provided by Garfish/Modern.js
174
+ export default function PluginApp({ basename }: { basename: string }) {
175
+ return (
176
+ <BrowserRouter basename={basename}>
177
+ <Routes>
178
+ <Route index element={<LoanCalculator />} />
179
+ <Route path="settings" element={<CalculatorSettings />} />
180
+ </Routes>
181
+ </BrowserRouter>
182
+ );
183
+ }
184
+ ```
185
+
186
+ ### 2.3 Accessing Shared State from Plugin
187
+
188
+ **File:** `plugins/@lego/plugin-loan-calculator/src/components/LoanCalculator.tsx`
189
+
190
+ ```typescript
191
+ import { useGarfish } from '@garfish/hooks';
192
+ import { useCallback } from 'react';
193
+
194
+ export function LoanCalculator() {
195
+ // Access shared state from host app
196
+ const { appInfo } = useGarfish();
197
+
198
+ const getGlobalState = useCallback(() => {
199
+ // The host app's useGlobalStore is available via Garfish's external system
200
+ return window.__LEGO_KERNEL_STATE__?.useGlobalStore;
201
+ }, []);
202
+
203
+ return (
204
+ <div>
205
+ <h1>Loan Calculator</h1>
206
+ {/* Plugin content */}
207
+ </div>
208
+ );
209
+ }
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 3. Shared Dependencies Strategy
215
+
216
+ ### 3.1 The Sharing Problem
217
+
218
+ **Problem:** How do we share `zustand` state between the Host and the Micro-frontend Plugin without double-loading React?
219
+
220
+ **Solution:** Modern.js + Garfish handle this through a **two-layer sharing strategy**:
221
+
222
+ 1. **Framework-Level Sharing (Automatic):** Modern.js's Garfish plugin automatically manages React, ReactDOM, and router sharing. No manual configuration needed.
223
+
224
+ 2. **Application-Level Sharing (Manual):** For business logic state (Zustand stores), use Garfish's `setExternal` API + a global window object pattern.
225
+
226
+ ### 3.2 Implementation: Shared State Bridge
227
+
228
+ **File:** `host/src/kernel/shared-state-bridge.ts`
229
+
230
+ ```typescript
231
+ import { create } from 'zustand';
232
+ import { devtools } from 'zustand/middleware';
233
+
234
+ // Define the shape of shared state
235
+ interface GlobalKernelState {
236
+ // User info
237
+ currentUser: { id: string; email: string; role: string } | null;
238
+
239
+ // UI State
240
+ theme: 'light' | 'dark';
241
+ sidebarOpen: boolean;
242
+
243
+ // Actions
244
+ setCurrentUser: (user: GlobalKernelState['currentUser']) => void;
245
+ setTheme: (theme: GlobalKernelState['theme']) => void;
246
+ toggleSidebar: () => void;
247
+ }
248
+
249
+ // Create the store
250
+ export const useGlobalKernelState = create<GlobalKernelState>()(
251
+ devtools(
252
+ (set) => ({
253
+ currentUser: null,
254
+ theme: 'light',
255
+ sidebarOpen: true,
256
+
257
+ setCurrentUser: (user) => set({ currentUser: user }),
258
+ setTheme: (theme) => set({ theme }),
259
+ toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
260
+ }),
261
+ { name: 'LegoKernelState' }
262
+ )
263
+ );
264
+
265
+ // Export a bridge function for plugins to access the store
266
+ export function registerSharedState() {
267
+ // Mount to window for plugin access
268
+ (window as any).__LEGO_KERNEL_STATE__ = {
269
+ useGlobalKernelState,
270
+ };
271
+ }
272
+ ```
273
+
274
+ **File:** `host/src/bootstrap.tsx` (updated)
275
+
276
+ ```typescript
277
+ import { registerSharedState } from './kernel/shared-state-bridge';
278
+
279
+ // Call this during host initialization
280
+ registerSharedState();
281
+ ```
282
+
283
+ ### 3.3 Plugin: Accessing Shared State
284
+
285
+ **File:** `plugins/@lego/plugin-loan-calculator/src/hooks/useKernelState.ts`
286
+
287
+ ```typescript
288
+ import { useEffect, useState } from 'react';
289
+
290
+ interface KernelState {
291
+ currentUser: { id: string; email: string; role: string } | null;
292
+ theme: 'light' | 'dark';
293
+ sidebarOpen: boolean;
294
+ setCurrentUser: (user: any) => void;
295
+ setTheme: (theme: 'light' | 'dark') => void;
296
+ toggleSidebar: () => void;
297
+ }
298
+
299
+ // Hook for plugins to access kernel state
300
+ export function useKernelState() {
301
+ const [state, setState] = useState<KernelState | null>(null);
302
+
303
+ useEffect(() => {
304
+ // Access the shared state bridge
305
+ const kernelBridge = (window as any).__LEGO_KERNEL_STATE__;
306
+
307
+ if (kernelBridge?.useGlobalKernelState) {
308
+ // Subscribe to state changes
309
+ const unsubscribe = kernelBridge.useGlobalKernelState.subscribe(
310
+ (newState: KernelState) => {
311
+ setState(newState);
312
+ }
313
+ );
314
+
315
+ // Initialize with current state
316
+ setState(kernelBridge.useGlobalKernelState.getState());
317
+
318
+ return () => unsubscribe?.();
319
+ }
320
+ }, []);
321
+
322
+ return state;
323
+ }
324
+ ```
325
+
326
+ ---
327
+
328
+ ## 4. Preventing Double-Loading
329
+
330
+ ### 4.1 Modern.js Automatic Handling
331
+
332
+ The `@modern-js/plugin-garfish` automatically prevents double-loading of:
333
+
334
+ - `react`
335
+ - `react-dom`
336
+ - `@modern-js/runtime` (includes router)
337
+ - `react-router-dom`
338
+
339
+ **No additional externals configuration needed** in Rspack/Modern.js for these packages.
340
+
341
+ ### 4.2 Custom Shared Dependencies
342
+
343
+ For custom packages that need to be shared (like UI primitives):
344
+
345
+ **Host `modern.config.ts`:**
346
+
347
+ ```typescript
348
+ export default defineConfig({
349
+ // ... other config
350
+
351
+ source: {
352
+ // Define shared modules for plugins
353
+ alias: {
354
+ // Plugins will use host's Radix primitives
355
+ '@radix-ui/react-slot': require.resolve('@radix-ui/react-slot'),
356
+ '@radix-ui/react-dialog': require.resolve('@radix-ui/react-dialog'),
357
+ },
358
+ },
359
+ });
360
+ ```
361
+
362
+ **Plugin `modern.config.ts`:**
363
+
364
+ ```typescript
365
+ export default defineConfig({
366
+ // ... other config
367
+
368
+ source: {
369
+ // Mark as external - will be provided by host
370
+ alias: {
371
+ '@radix-ui/react-slot': false,
372
+ '@radix-ui/react-dialog': false,
373
+ },
374
+ },
375
+ });
376
+ ```
377
+
378
+ ---
379
+
380
+ ## 5. Build Configuration for Production
381
+
382
+ ### 5.1 Production Build (Single Server)
383
+
384
+ ```bash
385
+ # From root - builds host + all plugins together
386
+ pnpm run build
387
+ ```
388
+
389
+ Expected output structure:
390
+ ```
391
+ host/
392
+ ├── dist/
393
+ │ ├── html/
394
+ │ │ └── index.html
395
+ │ ├── static/
396
+ │ │ ├── js/
397
+ │ │ │ ├── main-[hash].js # Host bundle
398
+ │ │ │ ├── vendor-[hash].js # Shared deps (React, Zustand)
399
+ │ │ │ └── plugins/ ← PLUGINS BUNDLED HERE
400
+ │ │ │ ├── dashboard-[hash].js
401
+ │ │ │ ├── loan-calc-[hash].js
402
+ │ │ │ └── inventory-[hash].js
403
+ │ │ ├── css/
404
+ │ │ │ └── main-[hash].css
405
+ │ │ └── assets/
406
+ ```
407
+
408
+ **IMPORTANT:** In production, **plugins are bundled into the host's `dist/` folder**. This means:
409
+ - Single deployment (`host/dist/` only)
410
+ - One URL for the entire application
411
+ - Plugins are code-split and loaded on-demand
412
+ - No separate plugin deployments needed
413
+
414
+ ### 5.2 Development Build (Separate Servers)
415
+
416
+ Each plugin can also build independently for development/testing:
417
+
418
+ ```bash
419
+ cd plugins/@lego/plugin-loan-calculator
420
+ pnpm run build
421
+ ```
422
+
423
+ Expected output structure:
424
+ ```
425
+ plugins/@lego/plugin-loan-calculator/
426
+ ├── dist/
427
+ │ ├── html/
428
+ │ │ └── index.html
429
+ │ ├── static/
430
+ │ │ ├── js/
431
+ │ │ ├── css/
432
+ │ │ └── assets/
433
+ ```
434
+
435
+ **IMPORTANT:** Each plugin builds as a **standalone application** that can be:
436
+ 1. Run independently in development (at `http://localhost:3001`, etc.)
437
+ 2. Loaded dynamically by the host in development
438
+ 3. Bundled into host for production (via dynamic `import()`)
439
+
440
+ ---
441
+
442
+ ## 6. Key API Names Reference
443
+
444
+ | API | Purpose | Location |
445
+ |-----|---------|----------|
446
+ | `garfishPlugin()` | Register Garfish MFE support | `modern.config.ts` |
447
+ | `defineRuntimeConfig()` | Configure sub-app list | `modern.runtime.ts` |
448
+ | `useModuleApps()` | Get loaded sub-app components | Component files |
449
+ | `Garfish.setExternal()` | Register shared dependencies | Bootstrap files |
450
+ | `Garfish.loadApp()` | Dynamically load a sub-app | Runtime code |
451
+ | `Garfish.channel` | Inter-app communication bus | Runtime code |
452
+
453
+ ---
454
+
455
+ ## 7. Configuration Checklist
456
+
457
+ ### Host App (Kernel)
458
+ - [ ] Register `garfishPlugin()` in `modern.config.ts`
459
+ - [ ] Enable `runtime.router: true`
460
+ - [ ] Configure `masterApp.apps` in `modern.runtime.ts`
461
+ - [ ] Set up shared state bridge with `Garfish.setExternal()`
462
+ - [ ] Create route entries (`$.tsx`) for each plugin
463
+ - [ ] Configure shared UI primitives (Radix, Zustand)
464
+
465
+ ### Sub-App (Plugin)
466
+ - [ ] Register `garfishPlugin()` in `modern.config.ts`
467
+ - [ ] Set `deploy.microFrontend: true`
468
+ - [ ] Configure unique `dev.port` for each plugin
469
+ - [ ] Export component accepting `basename` prop
470
+ - [ ] Use `@modern-js/runtime/router` with `basename`
471
+ - [ ] Configure external dependencies matching host
472
+
473
+ ---
474
+
475
+ ## 8. Next Steps
476
+
477
+ 1. **`01-system-blueprint.md`**: High-level architecture diagrams
478
+ 2. **`02-data-migration-protocol.md`**: PocketBase schema synchronization
479
+ 3. **`03-host-setup.md`**: Step-by-step host initialization with Tailwind/Shadcn
480
+
481
+ ---
482
+
483
+ ## References
484
+
485
+ - [Modern.js Micro Frontend Development Guide](https://modernjs.dev/guides/topic-detail/micro-frontend/c02-development)
486
+ - [Garfish.setExternal API Documentation](https://www.garfishjs.org/api/setExternal.html)
487
+ - [Rspack Module Federation Guide](https://rspack.rs/guide/features/module-federation)
488
+ - [Garfish GitHub Repository](https://github.com/web-infra-dev/garfish)