create-lego-one 2.0.12 → 2.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +150 -15
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
- package/template/.cursor/rules/rules.mdc +639 -0
- package/template/.dockerignore +58 -0
- package/template/.env.example +18 -0
- package/template/.eslintignore +5 -0
- package/template/.eslintrc.js +28 -0
- package/template/.prettierignore +6 -0
- package/template/.prettierrc +11 -0
- package/template/CLAUDE.md +634 -0
- package/template/Dockerfile +67 -0
- package/template/PROMPT.md +457 -0
- package/template/README.md +325 -0
- package/template/docker-compose.yml +48 -0
- package/template/docker-entrypoint.sh +23 -0
- package/template/docs/checkpoints/.template.md +64 -0
- package/template/docs/checkpoints/framework/01-infrastructure-setup.md +132 -0
- package/template/docs/checkpoints/framework/02-pocketbase-setup.md +155 -0
- package/template/docs/checkpoints/framework/03-host-kernel.md +170 -0
- package/template/docs/checkpoints/framework/04-auth-system.md +163 -0
- package/template/docs/checkpoints/framework/phase-05-multitenancy-rbac.md +223 -0
- package/template/docs/checkpoints/framework/phase-06-ui-components.md +260 -0
- package/template/docs/checkpoints/framework/phase-07-communication-system.md +276 -0
- package/template/docs/checkpoints/framework/phase-08-plugin-system.md +91 -0
- package/template/docs/checkpoints/framework/phase-09-dashboard-plugin.md +111 -0
- package/template/docs/checkpoints/framework/phase-10-todo-plugin.md +169 -0
- package/template/docs/checkpoints/framework/phase-11-testing.md +264 -0
- package/template/docs/checkpoints/framework/phase-12-deployment.md +294 -0
- package/template/docs/checkpoints/framework/phase-13-documentation.md +312 -0
- package/template/docs/framework/plans/00-index.md +164 -0
- package/template/docs/framework/plans/01-infrastructure-setup.md +855 -0
- package/template/docs/framework/plans/02-pocketbase-setup.md +1374 -0
- package/template/docs/framework/plans/03-host-kernel.md +1518 -0
- package/template/docs/framework/plans/04-auth-system.md +1466 -0
- package/template/docs/framework/plans/05-multitenancy-rbac.md +1527 -0
- package/template/docs/framework/plans/06-ui-components.md +1478 -0
- package/template/docs/framework/plans/07-communication-system.md +1106 -0
- package/template/docs/framework/plans/08-plugin-system.md +1179 -0
- package/template/docs/framework/plans/09-dashboard-plugin.md +1137 -0
- package/template/docs/framework/plans/10-todo-plugin.md +1343 -0
- package/template/docs/framework/plans/11-testing.md +935 -0
- package/template/docs/framework/plans/12-deployment.md +896 -0
- package/template/docs/framework/prompts/0-boilerplate-modernjs.md +151 -0
- package/template/docs/framework/research/00-modernjs-audit.md +488 -0
- package/template/docs/framework/research/01-system-blueprint.md +721 -0
- package/template/docs/framework/research/02-data-migration-protocol.md +699 -0
- package/template/docs/framework/research/03-host-setup.md +714 -0
- package/template/docs/framework/research/04-plugin-architecture.md +645 -0
- package/template/docs/framework/research/05-slot-injection-pattern.md +671 -0
- package/template/docs/framework/research/06-cli-strategy.md +615 -0
- package/template/docs/framework/research/07-deployment.md +629 -0
- package/template/docs/framework/research/README.md +282 -0
- package/template/docs/framework/setup/00-index.md +210 -0
- package/template/docs/framework/setup/01-framework-structure.md +308 -0
- package/template/docs/framework/setup/02-development-workflow.md +405 -0
- package/template/docs/framework/setup/03-environment-setup.md +215 -0
- package/template/docs/framework/setup/04-kernel-architecture.md +499 -0
- package/template/docs/framework/setup/05-plugin-system.md +620 -0
- package/template/docs/framework/setup/06-communication-patterns.md +451 -0
- package/template/docs/framework/setup/07-plugin-development.md +582 -0
- package/template/docs/framework/setup/08-component-library.md +658 -0
- package/template/docs/framework/setup/09-data-integration.md +609 -0
- package/template/docs/framework/setup/10-auth-rbac.md +497 -0
- package/template/docs/framework/setup/11-hooks-api.md +393 -0
- package/template/docs/framework/setup/12-components-api.md +665 -0
- package/template/docs/framework/setup/13-deployment-guide.md +566 -0
- package/template/docs/framework/setup/README.md +548 -0
- package/template/host/package.json +1 -1
- package/template/nginx.conf +72 -0
- package/template/package.json +1 -1
- package/template/packages/plugins/@lego/plugin-dashboard/package.json +1 -1
- package/template/packages/plugins/@lego/plugin-todo/package.json +1 -1
- package/template/pocketbase/CHANGELOG.md +911 -0
- package/template/pocketbase/LICENSE.md +17 -0
- package/template/scripts/create-plugin.js +221 -0
- package/template/scripts/deploy.sh +56 -0
- package/template/tsconfig.base.json +26 -0
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
# Deployment Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For AI Implementing This Plan:** This is document 12 of 13. Complete documents 01-11 first.
|
|
4
|
+
|
|
5
|
+
**Goal:** Configure build system for development and production environments, set up deployment scripts, and create CI/CD pipeline configuration.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Development: Separate plugin servers. Production: Single bundled deployment. Environment variables for configuration. Docker support for containerization.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Modern.js build system, Docker, GitHub Actions CI/CD, environment variable management
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
- ✅ Completed all documents 01-11
|
|
16
|
+
- ✅ Application builds and runs locally
|
|
17
|
+
- ✅ All tests pass
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Task 1: Create Environment Configuration
|
|
22
|
+
|
|
23
|
+
**Files:**
|
|
24
|
+
- Create: `.env.example`
|
|
25
|
+
- Create: `.env.development.example`
|
|
26
|
+
- Create: `.env.production.example`
|
|
27
|
+
- Create: `host/.env.example`
|
|
28
|
+
|
|
29
|
+
### Step 1: Create root environment examples
|
|
30
|
+
|
|
31
|
+
**File:** `.env.example`
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# PocketBase Configuration
|
|
35
|
+
VITE_POCKETBASE_URL=http://127.0.0.1:8090
|
|
36
|
+
|
|
37
|
+
# Application Configuration
|
|
38
|
+
VITE_APP_NAME=Lego-One
|
|
39
|
+
VITE_APP_URL=http://localhost:8080
|
|
40
|
+
|
|
41
|
+
# Feature Flags
|
|
42
|
+
VITE_ENABLE_ANALYTICS=false
|
|
43
|
+
VITE_ENABLE_ERROR_REPORTING=false
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**File:** `.env.development.example`
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Development Environment
|
|
50
|
+
NODE_ENV=development
|
|
51
|
+
|
|
52
|
+
# PocketBase (local development)
|
|
53
|
+
VITE_POCKETBASE_URL=http://127.0.0.1:8090
|
|
54
|
+
|
|
55
|
+
# Application URLs
|
|
56
|
+
VITE_APP_URL=http://localhost:8080
|
|
57
|
+
VITE_HOST_PORT=8080
|
|
58
|
+
VITE_DASHBOARD_PORT=3001
|
|
59
|
+
VITE_TODO_PORT=3002
|
|
60
|
+
|
|
61
|
+
# Feature Flags (development)
|
|
62
|
+
VITE_ENABLE_DEV_TOOLS=true
|
|
63
|
+
VITE_ENABLE_HOT_RELOAD=true
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**File:** `.env.production.example`
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Production Environment
|
|
70
|
+
NODE_ENV=production
|
|
71
|
+
|
|
72
|
+
# PocketBase (production - update with actual URL)
|
|
73
|
+
VITE_POCKETBASE_URL=https://your-pocketbase-url.com
|
|
74
|
+
|
|
75
|
+
# Application URLs
|
|
76
|
+
VITE_APP_URL=https://your-app-url.com
|
|
77
|
+
|
|
78
|
+
# Feature Flags (production)
|
|
79
|
+
VITE_ENABLE_DEV_TOOLS=false
|
|
80
|
+
VITE_ENABLE_HOT_RELOAD=false
|
|
81
|
+
VITE_ENABLE_ANALYTICS=true
|
|
82
|
+
VITE_ENABLE_ERROR_REPORTING=true
|
|
83
|
+
|
|
84
|
+
# Analytics (optional)
|
|
85
|
+
VITE_GA_ID=your-google-analytics-id
|
|
86
|
+
VITE_SENTRY_DSN=your-sentry-dsn
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 2: Create host environment example
|
|
90
|
+
|
|
91
|
+
**File:** `host/.env.example`
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# PocketBase URL (required)
|
|
95
|
+
VITE_POCKETBASE_URL=http://127.0.0.1:8090
|
|
96
|
+
|
|
97
|
+
# App Configuration
|
|
98
|
+
VITE_APP_NAME=Lego-One
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Task 2: Create Build Configuration
|
|
104
|
+
|
|
105
|
+
**Files:**
|
|
106
|
+
- Create: `scripts/build.sh`
|
|
107
|
+
- Create: `scripts/build-all.sh`
|
|
108
|
+
- Modify: `package.json` (root)
|
|
109
|
+
|
|
110
|
+
### Step 1: Create build script
|
|
111
|
+
|
|
112
|
+
**File:** `scripts/build.sh`
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
#!/bin/bash
|
|
116
|
+
set -e
|
|
117
|
+
|
|
118
|
+
echo "🏗️ Building Lego-One..."
|
|
119
|
+
|
|
120
|
+
# Load environment variables
|
|
121
|
+
if [ -f .env.production ]; then
|
|
122
|
+
export $(cat .env.production | grep -v '^#' | xargs)
|
|
123
|
+
else
|
|
124
|
+
echo "⚠️ Warning: .env.production not found"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Build host
|
|
128
|
+
echo "📦 Building host..."
|
|
129
|
+
cd host
|
|
130
|
+
pnpm run build
|
|
131
|
+
cd ..
|
|
132
|
+
|
|
133
|
+
echo "✅ Build complete!"
|
|
134
|
+
echo "📁 Output: host/dist/"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Step 2: Create build all script
|
|
138
|
+
|
|
139
|
+
**File:** `scripts/build-all.sh`
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
#!/bin/bash
|
|
143
|
+
set -e
|
|
144
|
+
|
|
145
|
+
echo "🏗️ Building Lego-One (Production)..."
|
|
146
|
+
|
|
147
|
+
# Load environment variables
|
|
148
|
+
if [ -f .env.production ]; then
|
|
149
|
+
export $(cat .env.production | grep -v '^#' | xargs)
|
|
150
|
+
else
|
|
151
|
+
echo "⚠️ Warning: .env.production not found, using defaults"
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# Check for required environment variables
|
|
155
|
+
if [ -z "$VITE_POCKETBASE_URL" ]; then
|
|
156
|
+
echo "❌ Error: VITE_POCKETBASE_URL is required"
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
echo "🔧 Configuration:"
|
|
161
|
+
echo " PocketBase: $VITE_POCKETBASE_URL"
|
|
162
|
+
echo " App URL: ${VITE_APP_URL:-https://your-app-url.com}"
|
|
163
|
+
|
|
164
|
+
# Build host (includes bundled plugins)
|
|
165
|
+
echo ""
|
|
166
|
+
echo "📦 Building host application..."
|
|
167
|
+
cd host
|
|
168
|
+
pnpm run build
|
|
169
|
+
|
|
170
|
+
if [ $? -ne 0 ]; then
|
|
171
|
+
echo "❌ Build failed"
|
|
172
|
+
exit 1
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
cd ..
|
|
176
|
+
|
|
177
|
+
echo ""
|
|
178
|
+
echo "✅ Build successful!"
|
|
179
|
+
echo ""
|
|
180
|
+
echo "📁 Output directory: host/dist/"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "🚀 To deploy:"
|
|
183
|
+
echo " 1. Copy host/dist/ to your server"
|
|
184
|
+
echo " 2. Configure your web server to serve static files"
|
|
185
|
+
echo " 3. Set up PocketBase at: $VITE_POCKETBASE_URL"
|
|
186
|
+
echo ""
|
|
187
|
+
echo "📊 Build size:"
|
|
188
|
+
du -sh host/dist
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Step 3: Add build scripts to package.json
|
|
192
|
+
|
|
193
|
+
**File:** `package.json` (root)
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"scripts": {
|
|
198
|
+
"build": "bash scripts/build-all.sh",
|
|
199
|
+
"build:host": "cd host && pnpm run build",
|
|
200
|
+
"dev": "pnpm run dev:host",
|
|
201
|
+
"dev:host": "cd host && pnpm run dev",
|
|
202
|
+
"dev:all": "concurrently \"pnpm:dev:*\" --kill-others",
|
|
203
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
204
|
+
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
205
|
+
"clean": "rm -rf host/dist node_modules/.cache"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Task 3: Create Development Scripts
|
|
213
|
+
|
|
214
|
+
**Files:**
|
|
215
|
+
- Create: `scripts/dev.sh`
|
|
216
|
+
- Modify: `package.json` (root)
|
|
217
|
+
|
|
218
|
+
### Step 1: Create development script
|
|
219
|
+
|
|
220
|
+
**File:** `scripts/dev.sh`
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
#!/bin/bash
|
|
224
|
+
set -e
|
|
225
|
+
|
|
226
|
+
echo "🚀 Starting Lego-One development servers..."
|
|
227
|
+
|
|
228
|
+
# Check if required ports are available
|
|
229
|
+
check_port() {
|
|
230
|
+
if lsof -Pi :$1 -sTCP:LISTEN -t >/dev/null 2>&1 ; then
|
|
231
|
+
echo "⚠️ Warning: Port $1 is already in use"
|
|
232
|
+
read -p "Kill process and continue? (y/n) " -n 1 -r
|
|
233
|
+
echo
|
|
234
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
235
|
+
lsof -ti:$1 | xargs kill -9
|
|
236
|
+
echo "✅ Killed process on port $1"
|
|
237
|
+
else
|
|
238
|
+
echo "❌ Cannot start server, port $1 is in use"
|
|
239
|
+
exit 1
|
|
240
|
+
fi
|
|
241
|
+
fi
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
check_port 8080 # Host
|
|
245
|
+
check_port 3001 # Dashboard plugin
|
|
246
|
+
check_port 3002 # Todo plugin
|
|
247
|
+
|
|
248
|
+
# Start all servers in parallel
|
|
249
|
+
echo ""
|
|
250
|
+
echo "🏠 Starting host on :8080..."
|
|
251
|
+
cd host && pnpm run dev &
|
|
252
|
+
HOST_PID=$!
|
|
253
|
+
cd ..
|
|
254
|
+
|
|
255
|
+
echo "📊 Starting dashboard plugin on :3001..."
|
|
256
|
+
cd packages/plugins/@lego/plugin-dashboard && pnpm run dev &
|
|
257
|
+
DASHBOARD_PID=$!
|
|
258
|
+
cd ../../..
|
|
259
|
+
|
|
260
|
+
echo "✓ Starting todo plugin on :3002..."
|
|
261
|
+
cd packages/plugins/@lego/plugin-todo && pnpm run dev &
|
|
262
|
+
TODO_PID=$!
|
|
263
|
+
cd ../../..
|
|
264
|
+
|
|
265
|
+
echo ""
|
|
266
|
+
echo "✅ All servers started!"
|
|
267
|
+
echo ""
|
|
268
|
+
echo "🌐 Available URLs:"
|
|
269
|
+
echo " - Host: http://localhost:8080"
|
|
270
|
+
echo " - Dashboard: http://localhost:3001 (standalone)"
|
|
271
|
+
echo " - Todos: http://localhost:3002 (standalone)"
|
|
272
|
+
echo ""
|
|
273
|
+
echo "Press Ctrl+C to stop all servers"
|
|
274
|
+
|
|
275
|
+
# Handle cleanup on exit
|
|
276
|
+
cleanup() {
|
|
277
|
+
echo ""
|
|
278
|
+
echo "🛑 Stopping all servers..."
|
|
279
|
+
kill $HOST_PID $DASHBOARD_PID $TODO_PID 2>/dev/null
|
|
280
|
+
echo "✅ All servers stopped"
|
|
281
|
+
exit 0
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
trap cleanup SIGINT SIGTERM
|
|
285
|
+
|
|
286
|
+
# Wait for any process to exit
|
|
287
|
+
wait
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Step 2: Add concurrently for dev mode
|
|
291
|
+
|
|
292
|
+
**File:** `package.json` (root)
|
|
293
|
+
|
|
294
|
+
Add to devDependencies:
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"devDependencies": {
|
|
299
|
+
"concurrently": "^9.0.1"
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Task 4: Create Docker Configuration
|
|
307
|
+
|
|
308
|
+
**Files:**
|
|
309
|
+
- Create: `Dockerfile`
|
|
310
|
+
- Create: `.dockerignore`
|
|
311
|
+
- Create: `docker-compose.yml`
|
|
312
|
+
- Create: `docker-compose.prod.yml`
|
|
313
|
+
|
|
314
|
+
### Step 1: Create Dockerfile
|
|
315
|
+
|
|
316
|
+
**File:** `Dockerfile`
|
|
317
|
+
|
|
318
|
+
```dockerfile
|
|
319
|
+
# Multi-stage build for production
|
|
320
|
+
|
|
321
|
+
# Build stage
|
|
322
|
+
FROM node:20-alpine AS builder
|
|
323
|
+
|
|
324
|
+
WORKDIR /app
|
|
325
|
+
|
|
326
|
+
# Install dependencies
|
|
327
|
+
COPY package.json pnpm-lock.yaml ./
|
|
328
|
+
COPY packages/host/package.json ./packages/host/
|
|
329
|
+
COPY packages/plugins/@lego/plugin-dashboard/package.json ./packages/plugins/@lego/plugin-dashboard/
|
|
330
|
+
COPY packages/plugins/@lego/plugin-todo/package.json ./packages/plugins/@lego/plugin-todo/
|
|
331
|
+
|
|
332
|
+
RUN npm install -g pnpm@9
|
|
333
|
+
RUN pnpm install --frozen-lockfile
|
|
334
|
+
|
|
335
|
+
# Copy source and build
|
|
336
|
+
COPY . .
|
|
337
|
+
|
|
338
|
+
# Build for production
|
|
339
|
+
ARG NODE_ENV=production
|
|
340
|
+
ENV NODE_ENV=$NODE_ENV
|
|
341
|
+
RUN pnpm run build
|
|
342
|
+
|
|
343
|
+
# Production stage
|
|
344
|
+
FROM nginx:alpine AS production
|
|
345
|
+
|
|
346
|
+
# Copy built files from build stage
|
|
347
|
+
COPY --from=builder /app/host/dist /usr/share/nginx/html
|
|
348
|
+
|
|
349
|
+
# Copy nginx configuration
|
|
350
|
+
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
|
351
|
+
|
|
352
|
+
# Expose port
|
|
353
|
+
EXPOSE 80
|
|
354
|
+
|
|
355
|
+
# Health check
|
|
356
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
357
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
|
|
358
|
+
|
|
359
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Step 2: Create nginx config
|
|
363
|
+
|
|
364
|
+
**File:** `docker/nginx.conf`
|
|
365
|
+
|
|
366
|
+
```nginx
|
|
367
|
+
server {
|
|
368
|
+
listen 80;
|
|
369
|
+
server_name _;
|
|
370
|
+
root /usr/share/nginx/html;
|
|
371
|
+
index index.html;
|
|
372
|
+
|
|
373
|
+
# Enable gzip compression
|
|
374
|
+
gzip on;
|
|
375
|
+
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
|
376
|
+
|
|
377
|
+
# Security headers
|
|
378
|
+
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
379
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
380
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
381
|
+
|
|
382
|
+
# SPA routing - redirect all routes to index.html
|
|
383
|
+
location / {
|
|
384
|
+
try_files $uri $uri/ /index.html;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
# Cache static assets
|
|
388
|
+
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
389
|
+
expires 1y;
|
|
390
|
+
add_header Cache-Control "public, immutable";
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
# Disable caching for HTML files
|
|
394
|
+
location ~* \.html$ {
|
|
395
|
+
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Step 3: Create dockerignore
|
|
401
|
+
|
|
402
|
+
**File:** `.dockerignore`
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
node_modules
|
|
406
|
+
npm-debug.log
|
|
407
|
+
.git
|
|
408
|
+
.gitignore
|
|
409
|
+
.env
|
|
410
|
+
.env.*
|
|
411
|
+
.vscode
|
|
412
|
+
.idea
|
|
413
|
+
*.md
|
|
414
|
+
docs
|
|
415
|
+
scripts
|
|
416
|
+
coverage
|
|
417
|
+
dist
|
|
418
|
+
.modern
|
|
419
|
+
.DS_Store
|
|
420
|
+
Thumbs.db
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Step 4: Create docker-compose for development
|
|
424
|
+
|
|
425
|
+
**File:** `docker-compose.yml`
|
|
426
|
+
|
|
427
|
+
```yaml
|
|
428
|
+
version: '3.8'
|
|
429
|
+
|
|
430
|
+
services:
|
|
431
|
+
pocketbase:
|
|
432
|
+
image: ghcr.io/muchb8/pocketbase:latest
|
|
433
|
+
container_name: lego-one-pb
|
|
434
|
+
ports:
|
|
435
|
+
- "8090:8090"
|
|
436
|
+
volumes:
|
|
437
|
+
- ./pocketbase/pb_data:/pb_data
|
|
438
|
+
environment:
|
|
439
|
+
- POCKETBASE_ENCRYPTION_ENV=automatic
|
|
440
|
+
restart: unless-stopped
|
|
441
|
+
|
|
442
|
+
# Development: Run host and plugins separately
|
|
443
|
+
host:
|
|
444
|
+
build:
|
|
445
|
+
context: .
|
|
446
|
+
dockerfile: Dockerfile.dev
|
|
447
|
+
container_name: lego-one-host
|
|
448
|
+
ports:
|
|
449
|
+
- "8080:8080"
|
|
450
|
+
environment:
|
|
451
|
+
- VITE_POCKETBASE_URL=http://pocketbase:8090
|
|
452
|
+
depends_on:
|
|
453
|
+
- pocketbase
|
|
454
|
+
volumes:
|
|
455
|
+
- ./host:/app/host
|
|
456
|
+
- ./packages:/app/packages
|
|
457
|
+
- /app/node_modules
|
|
458
|
+
command: pnpm run dev:host
|
|
459
|
+
restart: unless-stopped
|
|
460
|
+
|
|
461
|
+
volumes:
|
|
462
|
+
pb_data:
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Step 5: Create docker-compose for production
|
|
466
|
+
|
|
467
|
+
**File:** `docker-compose.prod.yml`
|
|
468
|
+
|
|
469
|
+
```yaml
|
|
470
|
+
version: '3.8'
|
|
471
|
+
|
|
472
|
+
services:
|
|
473
|
+
pocketbase:
|
|
474
|
+
image: ghcr.io/muchb8/pocketbase:latest
|
|
475
|
+
container_name: lego-one-pb
|
|
476
|
+
ports:
|
|
477
|
+
- "8090:8090"
|
|
478
|
+
volumes:
|
|
479
|
+
- ./pocketbase/pb_data:/pb_data
|
|
480
|
+
environment:
|
|
481
|
+
- POCKETBASE_ENCRYPTION_ENV=${POCKETBASE_ENCRYPTION_ENV}
|
|
482
|
+
restart: unless-stopped
|
|
483
|
+
networks:
|
|
484
|
+
- lego-network
|
|
485
|
+
|
|
486
|
+
app:
|
|
487
|
+
build:
|
|
488
|
+
context: .
|
|
489
|
+
dockerfile: Dockerfile
|
|
490
|
+
args:
|
|
491
|
+
NODE_ENV: production
|
|
492
|
+
container_name: lego-one-app
|
|
493
|
+
ports:
|
|
494
|
+
- "80:80"
|
|
495
|
+
environment:
|
|
496
|
+
- VITE_POCKETBASE_URL=${POCKETBASE_URL}
|
|
497
|
+
depends_on:
|
|
498
|
+
- pocketbase
|
|
499
|
+
restart: unless-stopped
|
|
500
|
+
networks:
|
|
501
|
+
- lego-network
|
|
502
|
+
|
|
503
|
+
volumes:
|
|
504
|
+
pb_data:
|
|
505
|
+
|
|
506
|
+
networks:
|
|
507
|
+
lego-network:
|
|
508
|
+
driver: bridge
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Task 5: Create CI/CD Pipeline
|
|
514
|
+
|
|
515
|
+
**Files:**
|
|
516
|
+
- Create: `.github/workflows/ci.yml`
|
|
517
|
+
- Create: `.github/workflows/deploy.yml`
|
|
518
|
+
|
|
519
|
+
### Step 1: Create CI workflow
|
|
520
|
+
|
|
521
|
+
**File:** `.github/workflows/ci.yml`
|
|
522
|
+
|
|
523
|
+
```yaml
|
|
524
|
+
name: CI
|
|
525
|
+
|
|
526
|
+
on:
|
|
527
|
+
push:
|
|
528
|
+
branches: [main, develop]
|
|
529
|
+
pull_request:
|
|
530
|
+
branches: [main, develop]
|
|
531
|
+
|
|
532
|
+
jobs:
|
|
533
|
+
lint:
|
|
534
|
+
name: Lint
|
|
535
|
+
runs-on: ubuntu-latest
|
|
536
|
+
steps:
|
|
537
|
+
- uses: actions/checkout@v4
|
|
538
|
+
|
|
539
|
+
- name: Setup pnpm
|
|
540
|
+
uses: pnpm/action-setup@v2
|
|
541
|
+
with:
|
|
542
|
+
version: 9
|
|
543
|
+
|
|
544
|
+
- name: Setup Node.js
|
|
545
|
+
uses: actions/setup-node@v4
|
|
546
|
+
with:
|
|
547
|
+
node-version: 20
|
|
548
|
+
cache: 'pnpm'
|
|
549
|
+
|
|
550
|
+
- name: Install dependencies
|
|
551
|
+
run: pnpm install
|
|
552
|
+
|
|
553
|
+
- name: Run ESLint
|
|
554
|
+
run: pnpm run lint
|
|
555
|
+
|
|
556
|
+
test:
|
|
557
|
+
name: Test
|
|
558
|
+
runs-on: ubuntu-latest
|
|
559
|
+
steps:
|
|
560
|
+
- uses: actions/checkout@v4
|
|
561
|
+
|
|
562
|
+
- name: Setup pnpm
|
|
563
|
+
uses: pnpm/action-setup@v2
|
|
564
|
+
with:
|
|
565
|
+
version: 9
|
|
566
|
+
|
|
567
|
+
- name: Setup Node.js
|
|
568
|
+
uses: actions/setup-node@v4
|
|
569
|
+
with:
|
|
570
|
+
node-version: 20
|
|
571
|
+
cache: 'pnpm'
|
|
572
|
+
|
|
573
|
+
- name: Install dependencies
|
|
574
|
+
run: pnpm install
|
|
575
|
+
|
|
576
|
+
- name: Run unit tests
|
|
577
|
+
run: pnpm run test:run
|
|
578
|
+
|
|
579
|
+
- name: Upload coverage
|
|
580
|
+
uses: codecov/codecov-action@v3
|
|
581
|
+
with:
|
|
582
|
+
files: ./coverage/coverage-final.json
|
|
583
|
+
|
|
584
|
+
build:
|
|
585
|
+
name: Build
|
|
586
|
+
runs-on: ubuntu-latest
|
|
587
|
+
needs: [lint, test]
|
|
588
|
+
steps:
|
|
589
|
+
- uses: actions/checkout@v4
|
|
590
|
+
|
|
591
|
+
- name: Setup pnpm
|
|
592
|
+
uses: pnpm/action-setup@v2
|
|
593
|
+
with:
|
|
594
|
+
version: 9
|
|
595
|
+
|
|
596
|
+
- name: Setup Node.js
|
|
597
|
+
uses: actions/setup-node@v4
|
|
598
|
+
with:
|
|
599
|
+
node-version: 20
|
|
600
|
+
cache: 'pnpm'
|
|
601
|
+
|
|
602
|
+
- name: Install dependencies
|
|
603
|
+
run: pnpm install
|
|
604
|
+
|
|
605
|
+
- name: Build application
|
|
606
|
+
run: pnpm run build
|
|
607
|
+
env:
|
|
608
|
+
VITE_POCKETBASE_URL: http://localhost:8090
|
|
609
|
+
|
|
610
|
+
- name: Upload build artifacts
|
|
611
|
+
uses: actions/upload-artifact@v3
|
|
612
|
+
with:
|
|
613
|
+
name: dist
|
|
614
|
+
path: host/dist/
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Step 2: Create deployment workflow
|
|
618
|
+
|
|
619
|
+
**File:** `.github/workflows/deploy.yml`
|
|
620
|
+
|
|
621
|
+
```yaml
|
|
622
|
+
name: Deploy
|
|
623
|
+
|
|
624
|
+
on:
|
|
625
|
+
push:
|
|
626
|
+
branches: [main]
|
|
627
|
+
workflow_dispatch:
|
|
628
|
+
|
|
629
|
+
jobs:
|
|
630
|
+
deploy:
|
|
631
|
+
name: Deploy to Production
|
|
632
|
+
runs-on: ubuntu-latest
|
|
633
|
+
steps:
|
|
634
|
+
- uses: actions/checkout@v4
|
|
635
|
+
|
|
636
|
+
- name: Setup pnpm
|
|
637
|
+
uses: pnpm/action-setup@v2
|
|
638
|
+
with:
|
|
639
|
+
version: 9
|
|
640
|
+
|
|
641
|
+
- name: Setup Node.js
|
|
642
|
+
uses: actions/setup-node@v4
|
|
643
|
+
with:
|
|
644
|
+
node-version: 20
|
|
645
|
+
cache: 'pnpm'
|
|
646
|
+
|
|
647
|
+
- name: Install dependencies
|
|
648
|
+
run: pnpm install
|
|
649
|
+
|
|
650
|
+
- name: Build application
|
|
651
|
+
run: pnpm run build
|
|
652
|
+
env:
|
|
653
|
+
VITE_POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
|
|
654
|
+
|
|
655
|
+
- name: Deploy to server
|
|
656
|
+
uses: easingthemes/ssh-deploy@main
|
|
657
|
+
env:
|
|
658
|
+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
659
|
+
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
|
|
660
|
+
REMOTE_USER: ${{ secrets.REMOTE_USER }}
|
|
661
|
+
TARGET: /var/www/lego-one
|
|
662
|
+
with:
|
|
663
|
+
SOURCE: "host/dist/*"
|
|
664
|
+
ARGS: "-rlgoDzvc -i --delete"
|
|
665
|
+
|
|
666
|
+
- name: Restart services
|
|
667
|
+
uses: appleboy/ssh-action@master
|
|
668
|
+
with:
|
|
669
|
+
host: ${{ secrets.REMOTE_HOST }}
|
|
670
|
+
username: ${{ secrets.REMOTE_USER }}
|
|
671
|
+
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
672
|
+
script: |
|
|
673
|
+
cd /var/www/lego-one
|
|
674
|
+
docker-compose -f docker-compose.prod.yml pull
|
|
675
|
+
docker-compose -f docker-compose.prod.yml up -d --build
|
|
676
|
+
docker system prune -f
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
681
|
+
## Task 6: Create Production Deployment Guide
|
|
682
|
+
|
|
683
|
+
**Files:**
|
|
684
|
+
- Create: `docs/deployment.md`
|
|
685
|
+
|
|
686
|
+
### Step 1: Create deployment documentation
|
|
687
|
+
|
|
688
|
+
**File:** `docs/deployment.md`
|
|
689
|
+
|
|
690
|
+
```markdown
|
|
691
|
+
# Deployment Guide
|
|
692
|
+
|
|
693
|
+
## Prerequisites
|
|
694
|
+
|
|
695
|
+
- Server with Docker and Docker Compose installed
|
|
696
|
+
- Domain name configured
|
|
697
|
+
- SSL certificate (recommended)
|
|
698
|
+
|
|
699
|
+
## Environment Variables
|
|
700
|
+
|
|
701
|
+
Create `.env.production`:
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
POCKETBASE_URL=https://your-pocketbase-url.com
|
|
705
|
+
POCKETBASE_ENCRYPTION_ENV=your-encryption-key
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
## Deployment Steps
|
|
709
|
+
|
|
710
|
+
### Option 1: Docker Compose (Recommended)
|
|
711
|
+
|
|
712
|
+
1. Copy files to server:
|
|
713
|
+
```bash
|
|
714
|
+
rsync -avz --exclude 'node_modules' --exclude '.git' \
|
|
715
|
+
./ user@server:/var/www/lego-one/
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
2. SSH into server and deploy:
|
|
719
|
+
```bash
|
|
720
|
+
cd /var/www/lego-one
|
|
721
|
+
docker-compose -f docker-compose.prod.yml up -d --build
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
3. Configure reverse proxy (Nginx):
|
|
725
|
+
```nginx
|
|
726
|
+
server {
|
|
727
|
+
listen 443 ssl http2;
|
|
728
|
+
server_name your-domain.com;
|
|
729
|
+
|
|
730
|
+
ssl_certificate /path/to/cert.pem;
|
|
731
|
+
ssl_certificate_key /path/to/key.pem;
|
|
732
|
+
|
|
733
|
+
location / {
|
|
734
|
+
proxy_pass http://localhost:80;
|
|
735
|
+
proxy_set_header Host $host;
|
|
736
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Option 2: Manual Deployment
|
|
742
|
+
|
|
743
|
+
1. Build locally:
|
|
744
|
+
```bash
|
|
745
|
+
pnpm run build
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
2. Upload `host/dist/` to server
|
|
749
|
+
|
|
750
|
+
3. Configure web server to serve static files
|
|
751
|
+
|
|
752
|
+
## PocketBase Setup
|
|
753
|
+
|
|
754
|
+
1. Download PocketBase binary
|
|
755
|
+
2. Run migrations: `./pocketbase serve --migrationDir=pocketbase/migrations`
|
|
756
|
+
3. Configure reverse proxy for port 8090
|
|
757
|
+
|
|
758
|
+
## Monitoring
|
|
759
|
+
|
|
760
|
+
- Check logs: `docker-compose logs -f`
|
|
761
|
+
- Health check: `curl http://localhost/`
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
## Task 7: Create Deployment Scripts
|
|
767
|
+
|
|
768
|
+
**Files:**
|
|
769
|
+
- Create: `scripts/deploy.sh`
|
|
770
|
+
|
|
771
|
+
### Step 1: Create deployment script
|
|
772
|
+
|
|
773
|
+
**File:** `scripts/deploy.sh`
|
|
774
|
+
|
|
775
|
+
```bash
|
|
776
|
+
#!/bin/bash
|
|
777
|
+
set -e
|
|
778
|
+
|
|
779
|
+
# Configuration
|
|
780
|
+
SERVER_USER="${DEPLOY_USER:-root}"
|
|
781
|
+
SERVER_HOST="${DEPLOY_HOST:-localhost}"
|
|
782
|
+
SERVER_PATH="${DEPLOY_PATH:-/var/www/lego-one}"
|
|
783
|
+
|
|
784
|
+
echo "🚀 Deploying to $SERVER_USER@$SERVER_HOST:$SERVER_PATH"
|
|
785
|
+
|
|
786
|
+
# Build application
|
|
787
|
+
echo "📦 Building application..."
|
|
788
|
+
pnpm run build
|
|
789
|
+
|
|
790
|
+
# Deploy via rsync
|
|
791
|
+
echo "📤 Uploading files..."
|
|
792
|
+
rsync -avz --delete \
|
|
793
|
+
--exclude 'node_modules' \
|
|
794
|
+
--exclude '.git' \
|
|
795
|
+
--exclude 'coverage' \
|
|
796
|
+
--exclude '.env.*' \
|
|
797
|
+
host/dist/ \
|
|
798
|
+
$SERVER_USER@$SERVER_HOST:$SERVER_PATH/dist/
|
|
799
|
+
|
|
800
|
+
# Restart services
|
|
801
|
+
echo "🔄 Restarting services..."
|
|
802
|
+
ssh $SERVER_USER@$SERVER_HOST << 'ENDSSH'
|
|
803
|
+
cd $SERVER_PATH
|
|
804
|
+
docker-compose -f docker-compose.prod.yml pull
|
|
805
|
+
docker-compose -f docker-compose.prod.yml up -d --build
|
|
806
|
+
docker system prune -f
|
|
807
|
+
ENDSSH
|
|
808
|
+
|
|
809
|
+
echo "✅ Deployment complete!"
|
|
810
|
+
echo "🌐 https://$SERVER_HOST"
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
---
|
|
814
|
+
|
|
815
|
+
## Verification
|
|
816
|
+
|
|
817
|
+
### Step 1: Test production build
|
|
818
|
+
|
|
819
|
+
**Run:**
|
|
820
|
+
|
|
821
|
+
```bash
|
|
822
|
+
cp .env.production.example .env.production
|
|
823
|
+
# Edit .env.production with actual values
|
|
824
|
+
pnpm run build
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
Expected: Build completes successfully, `host/dist/` contains all files.
|
|
828
|
+
|
|
829
|
+
### Step 2: Test Docker build
|
|
830
|
+
|
|
831
|
+
**Run:**
|
|
832
|
+
|
|
833
|
+
```bash
|
|
834
|
+
docker build -t lego-one:test .
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
Expected: Docker image builds successfully.
|
|
838
|
+
|
|
839
|
+
### Step 3: Test Docker Compose
|
|
840
|
+
|
|
841
|
+
**Run:**
|
|
842
|
+
|
|
843
|
+
```bash
|
|
844
|
+
docker-compose -f docker-compose.prod.yml config
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
Expected: Configuration is valid.
|
|
848
|
+
|
|
849
|
+
---
|
|
850
|
+
|
|
851
|
+
## Summary
|
|
852
|
+
|
|
853
|
+
After completing this document, you will have:
|
|
854
|
+
|
|
855
|
+
1. ✅ Environment configuration for dev and production
|
|
856
|
+
2. ✅ Build scripts for single-command builds
|
|
857
|
+
3. ✅ Development script for running all servers
|
|
858
|
+
4. ✅ Docker configuration for containerization
|
|
859
|
+
5. ✅ Docker Compose for local development and production
|
|
860
|
+
6. ✅ CI/CD pipeline with GitHub Actions
|
|
861
|
+
7. ✅ Deployment scripts and documentation
|
|
862
|
+
8. ✅ Production-ready deployment strategy
|
|
863
|
+
|
|
864
|
+
**Next:** `13-setup-guide.md` - Create user guide for setup, plugin development, and configuration.
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
## Files Created
|
|
869
|
+
|
|
870
|
+
```
|
|
871
|
+
root/
|
|
872
|
+
├── .env.example
|
|
873
|
+
├── .env.development.example
|
|
874
|
+
├── .env.production.example
|
|
875
|
+
├── Dockerfile
|
|
876
|
+
├── .dockerignore
|
|
877
|
+
├── docker-compose.yml
|
|
878
|
+
├── docker-compose.prod.yml
|
|
879
|
+
├── docker/
|
|
880
|
+
│ └── nginx.conf
|
|
881
|
+
├── scripts/
|
|
882
|
+
│ ├── build.sh
|
|
883
|
+
│ ├── build-all.sh
|
|
884
|
+
│ ├── dev.sh
|
|
885
|
+
│ └── deploy.sh
|
|
886
|
+
└── .github/
|
|
887
|
+
└── workflows/
|
|
888
|
+
├── ci.yml
|
|
889
|
+
└── deploy.yml
|
|
890
|
+
|
|
891
|
+
host/
|
|
892
|
+
└── .env.example
|
|
893
|
+
|
|
894
|
+
docs/
|
|
895
|
+
└── deployment.md
|
|
896
|
+
```
|