leedstack 3.1.0
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/LICENSE +21 -0
- package/README.md +364 -0
- package/bin/create-stack.js +277 -0
- package/package.json +60 -0
- package/tools/templates/backend/go-echo/backend/.env.example +10 -0
- package/tools/templates/backend/go-echo/backend/cmd/server/main.go.ejs +57 -0
- package/tools/templates/backend/go-echo/backend/go.mod.ejs +10 -0
- package/tools/templates/backend/go-echo/backend/internal/handlers/example.go +15 -0
- package/tools/templates/backend/go-echo/backend/internal/handlers/health.go +13 -0
- package/tools/templates/backend/java-spring/backend/.env.example +10 -0
- package/tools/templates/backend/java-spring/backend/pom.xml.ejs +64 -0
- package/tools/templates/backend/java-spring/backend/src/main/java/com/app/Application.java.ejs +11 -0
- package/tools/templates/backend/java-spring/backend/src/main/java/com/app/config/SecurityConfig.java.ejs +64 -0
- package/tools/templates/backend/java-spring/backend/src/main/java/com/app/controller/ExampleController.java +19 -0
- package/tools/templates/backend/java-spring/backend/src/main/java/com/app/controller/HealthController.java +15 -0
- package/tools/templates/backend/java-spring/backend/src/main/resources/application.yml.ejs +20 -0
- package/tools/templates/backend/node-express/backend/.env.example +10 -0
- package/tools/templates/backend/node-express/backend/.eslintrc.json +21 -0
- package/tools/templates/backend/node-express/backend/.prettierrc +10 -0
- package/tools/templates/backend/node-express/backend/Dockerfile +52 -0
- package/tools/templates/backend/node-express/backend/README.md +68 -0
- package/tools/templates/backend/node-express/backend/package.json.ejs +37 -0
- package/tools/templates/backend/node-express/backend/src/index.ts.ejs +75 -0
- package/tools/templates/backend/node-express/backend/src/routes/health.ts +54 -0
- package/tools/templates/backend/node-express/backend/tsconfig.json +17 -0
- package/tools/templates/backend/python-fastapi/backend/.env.example +18 -0
- package/tools/templates/backend/python-fastapi/backend/README.md +73 -0
- package/tools/templates/backend/python-fastapi/backend/app/__init__.py +1 -0
- package/tools/templates/backend/python-fastapi/backend/app/main.py.ejs +68 -0
- package/tools/templates/backend/python-fastapi/backend/requirements.txt.ejs +22 -0
- package/tools/templates/base/.dockerignore +16 -0
- package/tools/templates/base/.env.example +31 -0
- package/tools/templates/base/.github/workflows/ci.yml.ejs +124 -0
- package/tools/templates/base/.github/workflows/deploy-separate.yml.example +144 -0
- package/tools/templates/base/.vscode/extensions.json +17 -0
- package/tools/templates/base/.vscode/settings.json +49 -0
- package/tools/templates/base/Makefile +98 -0
- package/tools/templates/base/README.md.ejs +118 -0
- package/tools/templates/base/docker-compose.yml.ejs +49 -0
- package/tools/templates/base/package.json.ejs +30 -0
- package/tools/templates/base/scripts/split-repos.sh +189 -0
- package/tools/templates/db/postgres/backend/java-spring/backend/pom.xml.ejs +81 -0
- package/tools/templates/db/postgres/backend/java-spring/backend/src/main/resources/application.yml.ejs +39 -0
- package/tools/templates/db/postgres/backend/java-spring/backend/src/main/resources/db/migration/V1__init.sql +17 -0
- package/tools/templates/db/postgres/backend/node-express/backend/.env.example +10 -0
- package/tools/templates/db/postgres/backend/node-express/backend/package.json.ejs +32 -0
- package/tools/templates/db/postgres/backend/node-express/backend/prisma/schema.prisma.ejs +39 -0
- package/tools/templates/frontend/angular/frontend/.env.example +9 -0
- package/tools/templates/frontend/angular/frontend/angular.json +66 -0
- package/tools/templates/frontend/angular/frontend/package.json.ejs +31 -0
- package/tools/templates/frontend/angular/frontend/src/app/app.component.ts +30 -0
- package/tools/templates/frontend/angular/frontend/src/app/app.routes.ts +18 -0
- package/tools/templates/frontend/angular/frontend/src/app/components/home.component.ts +24 -0
- package/tools/templates/frontend/angular/frontend/src/app/services/api.service.ts +48 -0
- package/tools/templates/frontend/angular/frontend/src/favicon.ico +1 -0
- package/tools/templates/frontend/angular/frontend/src/index.html +13 -0
- package/tools/templates/frontend/angular/frontend/src/main.ts +10 -0
- package/tools/templates/frontend/angular/frontend/src/styles.css +31 -0
- package/tools/templates/frontend/angular/frontend/tsconfig.app.json +9 -0
- package/tools/templates/frontend/angular/frontend/tsconfig.json +27 -0
- package/tools/templates/frontend/nextjs/frontend/.env.example +9 -0
- package/tools/templates/frontend/nextjs/frontend/next.config.js +37 -0
- package/tools/templates/frontend/nextjs/frontend/package.json.ejs +25 -0
- package/tools/templates/frontend/nextjs/frontend/src/app/globals.css +31 -0
- package/tools/templates/frontend/nextjs/frontend/src/app/layout.tsx +36 -0
- package/tools/templates/frontend/nextjs/frontend/src/app/page.tsx +19 -0
- package/tools/templates/frontend/nextjs/frontend/src/lib/api.ts +45 -0
- package/tools/templates/frontend/nextjs/frontend/tsconfig.json +27 -0
- package/tools/templates/frontend/react/frontend/.env.example +9 -0
- package/tools/templates/frontend/react/frontend/.eslintrc.json +32 -0
- package/tools/templates/frontend/react/frontend/.prettierrc +10 -0
- package/tools/templates/frontend/react/frontend/Dockerfile +37 -0
- package/tools/templates/frontend/react/frontend/README.md +54 -0
- package/tools/templates/frontend/react/frontend/index.html +13 -0
- package/tools/templates/frontend/react/frontend/nginx.conf +35 -0
- package/tools/templates/frontend/react/frontend/package.json.ejs +41 -0
- package/tools/templates/frontend/react/frontend/public/vite.svg +4 -0
- package/tools/templates/frontend/react/frontend/src/App.css +65 -0
- package/tools/templates/frontend/react/frontend/src/App.jsx +41 -0
- package/tools/templates/frontend/react/frontend/src/assets/react.svg +7 -0
- package/tools/templates/frontend/react/frontend/src/components/ErrorBoundary.jsx +62 -0
- package/tools/templates/frontend/react/frontend/src/components/Home.jsx +58 -0
- package/tools/templates/frontend/react/frontend/src/components/__tests__/Home.test.jsx +74 -0
- package/tools/templates/frontend/react/frontend/src/index.css +31 -0
- package/tools/templates/frontend/react/frontend/src/lib/api.js +42 -0
- package/tools/templates/frontend/react/frontend/src/lib/env.js +58 -0
- package/tools/templates/frontend/react/frontend/src/main.jsx +16 -0
- package/tools/templates/frontend/react/frontend/src/setupTests.js +8 -0
- package/tools/templates/frontend/react/frontend/vite.config.js +30 -0
- package/tools/templates/frontend/react/frontend/vitest.config.js +20 -0
- package/tools/templates/frontend/svelte/frontend/.env.example +9 -0
- package/tools/templates/frontend/svelte/frontend/package.json.ejs +21 -0
- package/tools/templates/frontend/svelte/frontend/src/app.html +12 -0
- package/tools/templates/frontend/svelte/frontend/src/lib/api.ts +45 -0
- package/tools/templates/frontend/svelte/frontend/src/routes/+layout.svelte +56 -0
- package/tools/templates/frontend/svelte/frontend/src/routes/+page.svelte +20 -0
- package/tools/templates/frontend/svelte/frontend/static/favicon.png +1 -0
- package/tools/templates/frontend/svelte/frontend/svelte.config.js +10 -0
- package/tools/templates/frontend/svelte/frontend/vite.config.js +9 -0
- package/tools/templates/frontend/vue/frontend/.env.example +9 -0
- package/tools/templates/frontend/vue/frontend/index.html +13 -0
- package/tools/templates/frontend/vue/frontend/package.json.ejs +20 -0
- package/tools/templates/frontend/vue/frontend/src/App.vue +60 -0
- package/tools/templates/frontend/vue/frontend/src/lib/api.js +42 -0
- package/tools/templates/frontend/vue/frontend/src/main.js +33 -0
- package/tools/templates/frontend/vue/frontend/src/views/ApiTest.vue +39 -0
- package/tools/templates/frontend/vue/frontend/src/views/Home.vue +30 -0
- package/tools/templates/frontend/vue/frontend/vite.config.js +9 -0
- package/tools/templates/modules/admin/backend/java-spring/backend/src/main/java/com/app/controller/AdminController.java +41 -0
- package/tools/templates/modules/admin/backend/java-spring/backend/src/main/java/com/app/entity/User.java +55 -0
- package/tools/templates/modules/admin/backend/java-spring/backend/src/main/java/com/app/repository/UserRepository.java +8 -0
- package/tools/templates/modules/admin/frontend/svelte/frontend/src/routes/dashboard/+page.svelte +93 -0
- package/tools/templates/modules/auth/backend/node-express/backend/src/middleware/auth.ts +42 -0
- package/tools/templates/modules/auth/frontend/svelte/frontend/src/hooks.client.ts +3 -0
- package/tools/templates/modules/auth/frontend/svelte/frontend/src/lib/auth.ts +104 -0
- package/tools/templates/modules/auth/frontend/svelte/frontend/src/routes/callback/+page.svelte +18 -0
- package/tools/templates/modules/auth/frontend/svelte/frontend/src/routes/login/+page.svelte +12 -0
- package/tools/templates/modules/chatbot/backend/node-express/backend/src/index.ts.ejs +69 -0
- package/tools/templates/modules/chatbot/backend/node-express/backend/src/routes/chatbot.ts.ejs +37 -0
- package/tools/templates/modules/chatbot/backend/node-express/backend/src/services/chatbotService.ts +124 -0
- package/tools/templates/modules/chatbot/backend/python-fastapi/backend/app/main.py.ejs +69 -0
- package/tools/templates/modules/chatbot/backend/python-fastapi/backend/app/routes/chatbot.py +38 -0
- package/tools/templates/modules/chatbot/backend/python-fastapi/backend/app/services/chatbot_service.py +123 -0
- package/tools/templates/modules/chatbot/backend/python-fastapi/backend/requirements.txt +1 -0
- package/tools/templates/modules/chatbot/frontend/react/frontend/src/App.jsx.ejs +74 -0
- package/tools/templates/modules/chatbot/frontend/react/frontend/src/components/Chatbot.css +198 -0
- package/tools/templates/modules/chatbot/frontend/react/frontend/src/components/Chatbot.jsx +113 -0
- package/tools/templates/modules/contact/backend/java-spring/backend/src/main/java/com/app/controller/ContactController.java +29 -0
- package/tools/templates/modules/contact/backend/java-spring/backend/src/main/java/com/app/entity/ContactMessage.java +66 -0
- package/tools/templates/modules/contact/backend/java-spring/backend/src/main/java/com/app/repository/ContactMessageRepository.java +8 -0
- package/tools/templates/modules/contact/backend/java-spring/backend/src/main/resources/db/migration/V2__contact.sql +7 -0
- package/tools/templates/modules/contact/frontend/svelte/frontend/src/routes/contact/+page.svelte +80 -0
- package/tools/templates/modules/payments/backend/java-spring/backend/src/main/java/com/app/controller/PaymentController.java +69 -0
- package/tools/templates/modules/payments/backend/node-express/backend/src/routes/payments.ts +30 -0
- package/tools/templates/modules/payments/backend/node-express/backend/src/routes/webhook.ts +36 -0
- package/tools/templates/modules/payments/frontend/svelte/frontend/src/lib/payments.ts +28 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
.PHONY: help install install-fast dev build clean db-up db-down db-reset setup
|
|
2
|
+
|
|
3
|
+
help: ## Show this help message
|
|
4
|
+
@echo 'Usage: make [target]'
|
|
5
|
+
@echo ''
|
|
6
|
+
@echo 'Available targets:'
|
|
7
|
+
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
|
8
|
+
|
|
9
|
+
setup: install db-up ## Complete setup (install + start database)
|
|
10
|
+
@echo "✅ Setup complete! Run 'make dev' to start"
|
|
11
|
+
|
|
12
|
+
install-fast: ## Install dependencies in parallel (faster)
|
|
13
|
+
@echo "📦 Installing dependencies in parallel..."
|
|
14
|
+
@(cd frontend && npm install) & \
|
|
15
|
+
<% if (backend === 'node-express') { -%>
|
|
16
|
+
(cd backend && npm install) & \
|
|
17
|
+
<% } else if (backend === 'python-fastapi') { -%>
|
|
18
|
+
(cd backend && python -m venv venv && . venv/bin/activate && pip install -r requirements.txt) & \
|
|
19
|
+
<% } else if (backend === 'java-spring') { -%>
|
|
20
|
+
(cd backend && mvn clean install -T 1C) & \
|
|
21
|
+
<% } else if (backend === 'go-echo') { -%>
|
|
22
|
+
(cd backend && go mod download) & \
|
|
23
|
+
<% } -%>
|
|
24
|
+
wait
|
|
25
|
+
@echo "✅ Dependencies installed (parallel)"
|
|
26
|
+
|
|
27
|
+
install: ## Install all dependencies (sequential)
|
|
28
|
+
@echo "📦 Installing dependencies..."
|
|
29
|
+
cd frontend && npm install
|
|
30
|
+
<% if (backend === 'node-express') { -%>
|
|
31
|
+
cd backend && npm install
|
|
32
|
+
<% } else if (backend === 'python-fastapi') { -%>
|
|
33
|
+
cd backend && python -m venv venv && . venv/bin/activate && pip install -r requirements.txt
|
|
34
|
+
<% } else if (backend === 'java-spring') { -%>
|
|
35
|
+
cd backend && mvn clean install
|
|
36
|
+
<% } else if (backend === 'go-echo') { -%>
|
|
37
|
+
cd backend && go mod download
|
|
38
|
+
<% } -%>
|
|
39
|
+
@echo "✅ Dependencies installed"
|
|
40
|
+
|
|
41
|
+
dev: ## Start development servers
|
|
42
|
+
@echo "🚀 Starting development servers..."
|
|
43
|
+
@echo "Run 'make db-up' first if database is not running"
|
|
44
|
+
<% if (backend === 'node-express') { -%>
|
|
45
|
+
npm run dev
|
|
46
|
+
<% } else { -%>
|
|
47
|
+
@echo "Start backend and frontend in separate terminals:"
|
|
48
|
+
@echo " Terminal 1: cd backend && <% if (backend === 'python-fastapi') { %>python -m app.main<% } else if (backend === 'java-spring') { %>mvn spring-boot:run<% } else if (backend === 'go-echo') { %>go run ./cmd/server<% } %>"
|
|
49
|
+
@echo " Terminal 2: cd frontend && npm run dev"
|
|
50
|
+
<% } -%>
|
|
51
|
+
|
|
52
|
+
build: ## Build for production
|
|
53
|
+
@echo "🏗️ Building for production..."
|
|
54
|
+
cd frontend && npm run build
|
|
55
|
+
<% if (backend === 'node-express') { -%>
|
|
56
|
+
cd backend && npm run build
|
|
57
|
+
<% } else if (backend === 'python-fastapi') { -%>
|
|
58
|
+
@echo "Python: No build step needed"
|
|
59
|
+
<% } else if (backend === 'java-spring') { -%>
|
|
60
|
+
cd backend && mvn clean package
|
|
61
|
+
<% } else if (backend === 'go-echo') { -%>
|
|
62
|
+
cd backend && go build -o bin/<%= appSlug %>-backend ./cmd/server
|
|
63
|
+
<% } -%>
|
|
64
|
+
@echo "✅ Build complete"
|
|
65
|
+
|
|
66
|
+
db-up: ## Start database container
|
|
67
|
+
@echo "🐳 Starting database..."
|
|
68
|
+
docker compose up -d db
|
|
69
|
+
@echo "⏳ Waiting for database to be ready..."
|
|
70
|
+
@sleep 5
|
|
71
|
+
@echo "✅ Database is ready"
|
|
72
|
+
|
|
73
|
+
db-down: ## Stop database container
|
|
74
|
+
@echo "🛑 Stopping database..."
|
|
75
|
+
docker compose down
|
|
76
|
+
|
|
77
|
+
db-reset: ## Reset database (WARNING: deletes all data)
|
|
78
|
+
@echo "⚠️ This will delete all database data!"
|
|
79
|
+
@read -p "Are you sure? [y/N] " -n 1 -r; \
|
|
80
|
+
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
|
|
81
|
+
docker compose down -v; \
|
|
82
|
+
docker compose up -d db; \
|
|
83
|
+
echo "✅ Database reset complete"; \
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
clean: ## Clean build artifacts
|
|
87
|
+
@echo "🧹 Cleaning..."
|
|
88
|
+
cd frontend && rm -rf node_modules dist build .next
|
|
89
|
+
<% if (backend === 'node-express') { -%>
|
|
90
|
+
cd backend && rm -rf node_modules dist build
|
|
91
|
+
<% } else if (backend === 'python-fastapi') { -%>
|
|
92
|
+
cd backend && rm -rf __pycache__ .pytest_cache venv
|
|
93
|
+
<% } else if (backend === 'java-spring') { -%>
|
|
94
|
+
cd backend && mvn clean
|
|
95
|
+
<% } else if (backend === 'go-echo') { -%>
|
|
96
|
+
cd backend && rm -rf bin
|
|
97
|
+
<% } -%>
|
|
98
|
+
@echo "✅ Clean complete"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# <%= AppName %>
|
|
2
|
+
|
|
3
|
+
Generated via `create-stack`.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
- **Frontend**: <%= frontend %>
|
|
8
|
+
- **Backend**: <%= backend %>
|
|
9
|
+
- **Database**: <%= db %>
|
|
10
|
+
<% if (modules.auth) { -%>
|
|
11
|
+
- **Auth**: <%= auth %>
|
|
12
|
+
<% } -%>
|
|
13
|
+
<% if (modules.payments) { -%>
|
|
14
|
+
- **Payments**: <%= payments %>
|
|
15
|
+
<% } -%>
|
|
16
|
+
|
|
17
|
+
## Quickstart
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Start the database
|
|
21
|
+
docker compose up -d
|
|
22
|
+
|
|
23
|
+
# Backend
|
|
24
|
+
cd backend
|
|
25
|
+
<% if (backend === 'java-spring') { -%>
|
|
26
|
+
# Java 21 required
|
|
27
|
+
mvn spring-boot:run
|
|
28
|
+
<% } else if (backend === 'node-express') { -%>
|
|
29
|
+
# Node >=20 required
|
|
30
|
+
npm install
|
|
31
|
+
npm run dev
|
|
32
|
+
<% } else if (backend === 'go-echo') { -%>
|
|
33
|
+
# Go >=1.22 required
|
|
34
|
+
go run ./cmd/server
|
|
35
|
+
<% } -%>
|
|
36
|
+
|
|
37
|
+
# Frontend (in a new terminal)
|
|
38
|
+
cd ../frontend
|
|
39
|
+
cp .env.example .env
|
|
40
|
+
npm install
|
|
41
|
+
npm run dev
|
|
42
|
+
```
|
|
43
|
+
<% if (modules.auth) { -%>
|
|
44
|
+
|
|
45
|
+
## Auth0 Setup
|
|
46
|
+
|
|
47
|
+
1. Create a **Single Page Application** in Auth0
|
|
48
|
+
2. Configure settings:
|
|
49
|
+
- **Allowed Callback URLs**: `http://localhost:5173/callback`
|
|
50
|
+
- **Allowed Logout URLs**: `http://localhost:5173`
|
|
51
|
+
- **Allowed Web Origins**: `http://localhost:5173`
|
|
52
|
+
3. Create an **API** in Auth0:
|
|
53
|
+
- **Identifier**: `https://api.<%= appSlug %>`
|
|
54
|
+
- Enable **RBAC**
|
|
55
|
+
<% if (modules.admin) { -%>
|
|
56
|
+
- Add `admin` permission
|
|
57
|
+
<% } -%>
|
|
58
|
+
4. Update `.env` files with Auth0 credentials:
|
|
59
|
+
- `PUBLIC_AUTH0_DOMAIN`
|
|
60
|
+
- `PUBLIC_AUTH0_CLIENT_ID`
|
|
61
|
+
- `PUBLIC_AUTH0_AUDIENCE`
|
|
62
|
+
- `AUTH0_DOMAIN` (backend)
|
|
63
|
+
- `AUTH0_AUDIENCE` (backend)
|
|
64
|
+
<% } -%>
|
|
65
|
+
<% if (modules.payments) { -%>
|
|
66
|
+
|
|
67
|
+
## Stripe Setup
|
|
68
|
+
|
|
69
|
+
1. Get your Stripe secret key from the [Stripe Dashboard](https://dashboard.stripe.com/test/apikeys)
|
|
70
|
+
2. Set `STRIPE_SECRET_KEY` in backend `.env`
|
|
71
|
+
3. Create a product and price in Stripe, note the price ID
|
|
72
|
+
4. For webhook testing in development:
|
|
73
|
+
```bash
|
|
74
|
+
stripe listen --forward-to localhost:8080/stripe/webhook
|
|
75
|
+
```
|
|
76
|
+
5. Set `STRIPE_WEBHOOK_SECRET` from the CLI output
|
|
77
|
+
<% } -%>
|
|
78
|
+
|
|
79
|
+
## Endpoints
|
|
80
|
+
|
|
81
|
+
<% if (modules.contact) { -%>
|
|
82
|
+
- `POST /api/contact` - Submit contact message
|
|
83
|
+
<% } -%>
|
|
84
|
+
<% if (modules.admin) { -%>
|
|
85
|
+
- `GET /api/admin/stats` - Get admin statistics (requires `admin` scope)
|
|
86
|
+
<% } -%>
|
|
87
|
+
<% if (modules.payments) { -%>
|
|
88
|
+
- `POST /api/payments/create-checkout-session` - Create Stripe checkout session
|
|
89
|
+
- `POST /stripe/webhook` - Stripe webhook handler (public)
|
|
90
|
+
<% } -%>
|
|
91
|
+
<% if (backend === 'java-spring') { -%>
|
|
92
|
+
- `GET /actuator/health` - Health check
|
|
93
|
+
<% } else { -%>
|
|
94
|
+
- `GET /health` - Health check
|
|
95
|
+
<% } -%>
|
|
96
|
+
|
|
97
|
+
## Efficiency & Production Notes
|
|
98
|
+
|
|
99
|
+
**Frontend**:
|
|
100
|
+
- SSR enabled where applicable
|
|
101
|
+
- Code-split routes
|
|
102
|
+
<% if (modules.admin) { -%>
|
|
103
|
+
- Admin module lazy-loaded
|
|
104
|
+
<% } -%>
|
|
105
|
+
- Minimal dependencies
|
|
106
|
+
|
|
107
|
+
**Backend**:
|
|
108
|
+
- JSON-only API
|
|
109
|
+
- JWT validation via JWKS
|
|
110
|
+
<% if (backend === 'java-spring') { -%>
|
|
111
|
+
- Flyway migrations for schema management
|
|
112
|
+
<% } else if (backend === 'node-express' && db !== 'mongodb') { -%>
|
|
113
|
+
- Prisma migrations for schema management
|
|
114
|
+
<% } -%>
|
|
115
|
+
|
|
116
|
+
**Docker**:
|
|
117
|
+
- Development uses only DB container
|
|
118
|
+
- For production, use multi-stage builds with minimal base images
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
services:
|
|
2
|
+
db:
|
|
3
|
+
<% if (db === 'postgres') { -%>
|
|
4
|
+
image: postgres:16
|
|
5
|
+
container_name: <%= appSlug %>-db
|
|
6
|
+
environment:
|
|
7
|
+
POSTGRES_USER: <%= appSlug %>
|
|
8
|
+
POSTGRES_PASSWORD: password
|
|
9
|
+
POSTGRES_DB: <%= appSlug %>_dev
|
|
10
|
+
ports:
|
|
11
|
+
- "5432:5432"
|
|
12
|
+
healthcheck:
|
|
13
|
+
test: ["CMD-SHELL", "pg_isready -U <%= appSlug %>"]
|
|
14
|
+
interval: 10s
|
|
15
|
+
timeout: 5s
|
|
16
|
+
retries: 5
|
|
17
|
+
<% } else if (db === 'mysql') { -%>
|
|
18
|
+
image: mysql:8
|
|
19
|
+
container_name: <%= appSlug %>-db
|
|
20
|
+
environment:
|
|
21
|
+
MYSQL_ROOT_PASSWORD: password
|
|
22
|
+
MYSQL_DATABASE: <%= appSlug %>_dev
|
|
23
|
+
MYSQL_USER: <%= appSlug %>
|
|
24
|
+
MYSQL_PASSWORD: password
|
|
25
|
+
ports:
|
|
26
|
+
- "3306:3306"
|
|
27
|
+
healthcheck:
|
|
28
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
29
|
+
interval: 10s
|
|
30
|
+
timeout: 5s
|
|
31
|
+
retries: 5
|
|
32
|
+
<% } else { -%>
|
|
33
|
+
image: mongo:7
|
|
34
|
+
container_name: <%= appSlug %>-db
|
|
35
|
+
ports:
|
|
36
|
+
- "27017:27017"
|
|
37
|
+
healthcheck:
|
|
38
|
+
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
|
39
|
+
interval: 10s
|
|
40
|
+
timeout: 5s
|
|
41
|
+
retries: 5
|
|
42
|
+
<% } -%>
|
|
43
|
+
volumes:
|
|
44
|
+
- db_data:/data
|
|
45
|
+
restart: unless-stopped
|
|
46
|
+
|
|
47
|
+
volumes:
|
|
48
|
+
db_data:
|
|
49
|
+
driver: local
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= appSlug %>",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "echo 'Starting development servers...' && npm-run-all --parallel dev:*",
|
|
7
|
+
"dev:backend": "cd backend && npm run dev",
|
|
8
|
+
"dev:frontend": "cd frontend && npm run dev",
|
|
9
|
+
"install:all": "npm-run-all --parallel install:*",
|
|
10
|
+
"install:backend": "cd backend && npm install",
|
|
11
|
+
"install:frontend": "cd frontend && npm install",
|
|
12
|
+
"build": "npm-run-all build:*",
|
|
13
|
+
"build:backend": "cd backend && npm run build",
|
|
14
|
+
"build:frontend": "cd frontend && npm run build",
|
|
15
|
+
"setup": "npm run install:all && echo '✅ All dependencies installed!'",
|
|
16
|
+
"start": "npm-run-all --parallel start:*",
|
|
17
|
+
"start:backend": "cd backend && npm start",
|
|
18
|
+
"start:frontend": "cd frontend && npm start",
|
|
19
|
+
"clean": "npm-run-all clean:*",
|
|
20
|
+
"clean:backend": "cd backend && rm -rf node_modules dist build",
|
|
21
|
+
"clean:frontend": "cd frontend && rm -rf node_modules dist build .next",
|
|
22
|
+
"reset": "npm run clean && npm run install:all"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"npm-run-all": "^4.1.5"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=20.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Script to split monorepo into separate frontend and backend repositories
|
|
4
|
+
# Usage: ./scripts/split-repos.sh
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🔀 Splitting monorepo into separate repositories..."
|
|
9
|
+
echo ""
|
|
10
|
+
|
|
11
|
+
# Get project name from current directory
|
|
12
|
+
PROJECT_NAME=$(basename "$PWD")
|
|
13
|
+
FRONTEND_REPO="${PROJECT_NAME}-frontend"
|
|
14
|
+
BACKEND_REPO="${PROJECT_NAME}-backend"
|
|
15
|
+
|
|
16
|
+
# Confirm with user
|
|
17
|
+
echo "This will create two new directories:"
|
|
18
|
+
echo " - ../$FRONTEND_REPO"
|
|
19
|
+
echo " - ../$BACKEND_REPO"
|
|
20
|
+
echo ""
|
|
21
|
+
read -p "Continue? (y/n) " -n 1 -r
|
|
22
|
+
echo
|
|
23
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Create frontend repo
|
|
28
|
+
echo ""
|
|
29
|
+
echo "📦 Creating frontend repository..."
|
|
30
|
+
cd ..
|
|
31
|
+
mkdir -p "$FRONTEND_REPO"
|
|
32
|
+
cd "$PROJECT_NAME"
|
|
33
|
+
|
|
34
|
+
# Copy frontend files
|
|
35
|
+
cp -r frontend/* "../$FRONTEND_REPO/"
|
|
36
|
+
cp -r frontend/.* "../$FRONTEND_REPO/" 2>/dev/null || true
|
|
37
|
+
|
|
38
|
+
# Copy shared files
|
|
39
|
+
cp .gitignore "../$FRONTEND_REPO/"
|
|
40
|
+
cp README.md "../$FRONTEND_REPO/README.md.bak"
|
|
41
|
+
|
|
42
|
+
# Initialize git
|
|
43
|
+
cd "../$FRONTEND_REPO"
|
|
44
|
+
rm -rf .git 2>/dev/null || true
|
|
45
|
+
git init
|
|
46
|
+
git add .
|
|
47
|
+
git commit -m "Initial commit: frontend"
|
|
48
|
+
|
|
49
|
+
echo "✅ Frontend repository created at ../$FRONTEND_REPO"
|
|
50
|
+
|
|
51
|
+
# Create backend repo
|
|
52
|
+
echo ""
|
|
53
|
+
echo "📦 Creating backend repository..."
|
|
54
|
+
cd "../$PROJECT_NAME"
|
|
55
|
+
mkdir -p "../$BACKEND_REPO"
|
|
56
|
+
|
|
57
|
+
# Copy backend files
|
|
58
|
+
cp -r backend/* "../$BACKEND_REPO/"
|
|
59
|
+
cp -r backend/.* "../$BACKEND_REPO/" 2>/dev/null || true
|
|
60
|
+
|
|
61
|
+
# Copy shared files
|
|
62
|
+
cp .gitignore "../$BACKEND_REPO/"
|
|
63
|
+
cp docker-compose.yml "../$BACKEND_REPO/" 2>/dev/null || true
|
|
64
|
+
cp README.md "../$BACKEND_REPO/README.md.bak"
|
|
65
|
+
|
|
66
|
+
# Initialize git
|
|
67
|
+
cd "../$BACKEND_REPO"
|
|
68
|
+
rm -rf .git 2>/dev/null || true
|
|
69
|
+
git init
|
|
70
|
+
git add .
|
|
71
|
+
git commit -m "Initial commit: backend"
|
|
72
|
+
|
|
73
|
+
echo "✅ Backend repository created at ../$BACKEND_REPO"
|
|
74
|
+
|
|
75
|
+
# Create instructions
|
|
76
|
+
cd "../$PROJECT_NAME"
|
|
77
|
+
cat > SPLIT_INSTRUCTIONS.md << 'EOF'
|
|
78
|
+
# Next Steps After Splitting Repositories
|
|
79
|
+
|
|
80
|
+
## 1. Create GitHub Repositories
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Create repos on GitHub, then:
|
|
84
|
+
|
|
85
|
+
# Frontend
|
|
86
|
+
cd ../PROJECT_NAME-frontend
|
|
87
|
+
git remote add origin https://github.com/USERNAME/PROJECT_NAME-frontend.git
|
|
88
|
+
git push -u origin main
|
|
89
|
+
|
|
90
|
+
# Backend
|
|
91
|
+
cd ../PROJECT_NAME-backend
|
|
92
|
+
git remote add origin https://github.com/USERNAME/PROJECT_NAME-backend.git
|
|
93
|
+
git push -u origin main
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 2. Update Environment Variables
|
|
97
|
+
|
|
98
|
+
### Frontend (.env)
|
|
99
|
+
```env
|
|
100
|
+
# Update API base URL to production backend
|
|
101
|
+
VITE_API_BASE=https://your-backend.fly.dev
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Backend (.env)
|
|
105
|
+
```env
|
|
106
|
+
# Add production frontend URL
|
|
107
|
+
FRONTEND_URL=https://your-app.vercel.app
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 3. Update CORS Configuration
|
|
111
|
+
|
|
112
|
+
### Backend (src/index.ts)
|
|
113
|
+
Add your production frontend URL to allowed origins:
|
|
114
|
+
```typescript
|
|
115
|
+
const allowedOrigins = [
|
|
116
|
+
'http://localhost:5173',
|
|
117
|
+
'http://localhost:3000',
|
|
118
|
+
'https://your-app.vercel.app', // Add this
|
|
119
|
+
process.env.FRONTEND_URL
|
|
120
|
+
].filter(Boolean);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 4. Set Up CI/CD
|
|
124
|
+
|
|
125
|
+
Copy the appropriate deployment workflow:
|
|
126
|
+
```bash
|
|
127
|
+
# Frontend
|
|
128
|
+
cp .github/workflows/deploy-separate.yml.example .github/workflows/deploy.yml
|
|
129
|
+
# Edit and keep only frontend section
|
|
130
|
+
|
|
131
|
+
# Backend
|
|
132
|
+
cp .github/workflows/deploy-separate.yml.example .github/workflows/deploy.yml
|
|
133
|
+
# Edit and keep only backend section
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 5. Deploy
|
|
137
|
+
|
|
138
|
+
### Frontend (Vercel - FREE)
|
|
139
|
+
```bash
|
|
140
|
+
cd ../PROJECT_NAME-frontend
|
|
141
|
+
npm install -g vercel
|
|
142
|
+
vercel --prod
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Backend (Fly.io - FREE)
|
|
146
|
+
```bash
|
|
147
|
+
cd ../PROJECT_NAME-backend
|
|
148
|
+
curl -L https://fly.io/install.sh | sh
|
|
149
|
+
fly auth login
|
|
150
|
+
fly launch
|
|
151
|
+
fly deploy
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Database (Supabase - FREE)
|
|
155
|
+
1. Create project at https://supabase.com
|
|
156
|
+
2. Get connection string
|
|
157
|
+
3. Set in backend: `fly secrets set DATABASE_URL=postgresql://...`
|
|
158
|
+
|
|
159
|
+
## 6. Update Frontend with Backend URL
|
|
160
|
+
|
|
161
|
+
After deploying backend, update frontend env vars:
|
|
162
|
+
```bash
|
|
163
|
+
# Vercel
|
|
164
|
+
vercel env add VITE_API_BASE production
|
|
165
|
+
# Enter: https://your-backend.fly.dev
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Done! 🎉
|
|
169
|
+
|
|
170
|
+
Your app is now deployed separately:
|
|
171
|
+
- Frontend: https://your-app.vercel.app (FREE)
|
|
172
|
+
- Backend: https://your-backend.fly.dev (FREE)
|
|
173
|
+
- Database: Supabase (FREE)
|
|
174
|
+
|
|
175
|
+
**Total cost: $0/month**
|
|
176
|
+
|
|
177
|
+
See DEPLOYMENT_STRATEGIES.md for more details.
|
|
178
|
+
EOF
|
|
179
|
+
|
|
180
|
+
echo ""
|
|
181
|
+
echo "✅ Split complete!"
|
|
182
|
+
echo ""
|
|
183
|
+
echo "📝 Next steps written to: SPLIT_INSTRUCTIONS.md"
|
|
184
|
+
echo ""
|
|
185
|
+
echo "Your repositories:"
|
|
186
|
+
echo " Frontend: ../$FRONTEND_REPO"
|
|
187
|
+
echo " Backend: ../$BACKEND_REPO"
|
|
188
|
+
echo ""
|
|
189
|
+
echo "Read SPLIT_INSTRUCTIONS.md for deployment steps."
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
4
|
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
5
|
+
<modelVersion>4.0.0</modelVersion>
|
|
6
|
+
|
|
7
|
+
<parent>
|
|
8
|
+
<groupId>org.springframework.boot</groupId>
|
|
9
|
+
<artifactId>spring-boot-starter-parent</artifactId>
|
|
10
|
+
<version>3.3.4</version>
|
|
11
|
+
<relativePath/>
|
|
12
|
+
</parent>
|
|
13
|
+
|
|
14
|
+
<groupId>com.app</groupId>
|
|
15
|
+
<artifactId><%= appSlug %>-backend</artifactId>
|
|
16
|
+
<version>0.0.1-SNAPSHOT</version>
|
|
17
|
+
<name><%= appName %> Backend</name>
|
|
18
|
+
|
|
19
|
+
<properties>
|
|
20
|
+
<java.version>21</java.version>
|
|
21
|
+
</properties>
|
|
22
|
+
|
|
23
|
+
<dependencies>
|
|
24
|
+
<dependency>
|
|
25
|
+
<groupId>org.springframework.boot</groupId>
|
|
26
|
+
<artifactId>spring-boot-starter-web</artifactId>
|
|
27
|
+
</dependency>
|
|
28
|
+
<dependency>
|
|
29
|
+
<groupId>org.springframework.boot</groupId>
|
|
30
|
+
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
31
|
+
</dependency>
|
|
32
|
+
<dependency>
|
|
33
|
+
<groupId>org.flywaydb</groupId>
|
|
34
|
+
<artifactId>flyway-core</artifactId>
|
|
35
|
+
</dependency>
|
|
36
|
+
<dependency>
|
|
37
|
+
<groupId>org.flywaydb</groupId>
|
|
38
|
+
<artifactId>flyway-database-postgresql</artifactId>
|
|
39
|
+
</dependency>
|
|
40
|
+
<dependency>
|
|
41
|
+
<groupId>org.postgresql</groupId>
|
|
42
|
+
<artifactId>postgresql</artifactId>
|
|
43
|
+
<scope>runtime</scope>
|
|
44
|
+
</dependency>
|
|
45
|
+
<% if (modules.auth) { -%>
|
|
46
|
+
<dependency>
|
|
47
|
+
<groupId>org.springframework.boot</groupId>
|
|
48
|
+
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
|
49
|
+
</dependency>
|
|
50
|
+
<dependency>
|
|
51
|
+
<groupId>org.springframework.boot</groupId>
|
|
52
|
+
<artifactId>spring-boot-starter-security</artifactId>
|
|
53
|
+
</dependency>
|
|
54
|
+
<% } -%>
|
|
55
|
+
<% if (modules.payments) { -%>
|
|
56
|
+
<dependency>
|
|
57
|
+
<groupId>com.stripe</groupId>
|
|
58
|
+
<artifactId>stripe-java</artifactId>
|
|
59
|
+
<version>26.0.0</version>
|
|
60
|
+
</dependency>
|
|
61
|
+
<% } -%>
|
|
62
|
+
<dependency>
|
|
63
|
+
<groupId>org.springframework.boot</groupId>
|
|
64
|
+
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
65
|
+
</dependency>
|
|
66
|
+
<dependency>
|
|
67
|
+
<groupId>org.springframework.boot</groupId>
|
|
68
|
+
<artifactId>spring-boot-starter-test</artifactId>
|
|
69
|
+
<scope>test</scope>
|
|
70
|
+
</dependency>
|
|
71
|
+
</dependencies>
|
|
72
|
+
|
|
73
|
+
<build>
|
|
74
|
+
<plugins>
|
|
75
|
+
<plugin>
|
|
76
|
+
<groupId>org.springframework.boot</groupId>
|
|
77
|
+
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
78
|
+
</plugin>
|
|
79
|
+
</plugins>
|
|
80
|
+
</build>
|
|
81
|
+
</project>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
server:
|
|
2
|
+
port: ${APP_PORT:8080}
|
|
3
|
+
|
|
4
|
+
spring:
|
|
5
|
+
application:
|
|
6
|
+
name: <%= appSlug %>-backend
|
|
7
|
+
|
|
8
|
+
datasource:
|
|
9
|
+
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:<%= appSlug %>_dev}
|
|
10
|
+
username: ${DB_USER:<%= appSlug %>}
|
|
11
|
+
password: ${DB_PASSWORD:password}
|
|
12
|
+
|
|
13
|
+
jpa:
|
|
14
|
+
hibernate:
|
|
15
|
+
ddl-auto: validate
|
|
16
|
+
properties:
|
|
17
|
+
hibernate:
|
|
18
|
+
jdbc:
|
|
19
|
+
time_zone: UTC
|
|
20
|
+
show-sql: false
|
|
21
|
+
|
|
22
|
+
flyway:
|
|
23
|
+
enabled: true
|
|
24
|
+
locations: classpath:db/migration
|
|
25
|
+
<% if (modules.auth) { -%>
|
|
26
|
+
|
|
27
|
+
security:
|
|
28
|
+
oauth2:
|
|
29
|
+
resourceserver:
|
|
30
|
+
jwt:
|
|
31
|
+
issuer-uri: https://${AUTH0_DOMAIN}/
|
|
32
|
+
audiences: ${AUTH0_AUDIENCE}
|
|
33
|
+
<% } -%>
|
|
34
|
+
|
|
35
|
+
management:
|
|
36
|
+
endpoints:
|
|
37
|
+
web:
|
|
38
|
+
exposure:
|
|
39
|
+
include: health
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
2
|
+
id BIGSERIAL PRIMARY KEY,
|
|
3
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
4
|
+
name VARCHAR(120),
|
|
5
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS roles (
|
|
9
|
+
id SERIAL PRIMARY KEY,
|
|
10
|
+
name VARCHAR(30) UNIQUE NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
CREATE TABLE IF NOT EXISTS user_roles (
|
|
14
|
+
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
|
|
15
|
+
role_id INT REFERENCES roles(id) ON DELETE CASCADE,
|
|
16
|
+
PRIMARY KEY (user_id, role_id)
|
|
17
|
+
);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
APP_PORT=8080
|
|
2
|
+
DATABASE_URL=postgresql://<%= appSlug %>:password@localhost:5432/<%= appSlug %>_dev
|
|
3
|
+
<% if (modules.auth) { -%>
|
|
4
|
+
AUTH0_DOMAIN=your-tenant.us.auth0.com
|
|
5
|
+
AUTH0_AUDIENCE=https://api.<%= appSlug %>
|
|
6
|
+
<% } -%>
|
|
7
|
+
<% if (modules.payments) { -%>
|
|
8
|
+
STRIPE_SECRET_KEY=sk_test_xxx
|
|
9
|
+
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
10
|
+
<% } -%>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= appSlug %>-backend",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.0.0"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsx watch src/index.ts",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"prisma:generate": "prisma generate",
|
|
14
|
+
"prisma:migrate": "prisma migrate dev"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"express": "^5.0.0",
|
|
18
|
+
"cors": "^2.8.5",
|
|
19
|
+
"dotenv": "^16.4.5",
|
|
20
|
+
"@prisma/client": "^6.0.0"<% if (modules.auth) { %>,
|
|
21
|
+
"jose": "^5.9.6"<% } %><% if (modules.payments) { %>,
|
|
22
|
+
"stripe": "^16.0.0"<% } %>
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/express": "^5.0.0",
|
|
26
|
+
"@types/cors": "^2.8.17",
|
|
27
|
+
"@types/node": "^22.0.0",
|
|
28
|
+
"prisma": "^6.0.0",
|
|
29
|
+
"tsx": "^4.19.2",
|
|
30
|
+
"typescript": "^5.6.3"
|
|
31
|
+
}
|
|
32
|
+
}
|