create-tigra 2.4.0 → 2.6.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.
Files changed (42) hide show
  1. package/bin/create-tigra.js +5 -2
  2. package/package.json +1 -1
  3. package/template/_claude/rules/client/01-project-structure.md +6 -0
  4. package/template/_claude/rules/client/04-design-system.md +67 -44
  5. package/template/_claude/rules/client/core.md +3 -2
  6. package/template/_claude/rules/global/completion-reports.md +178 -0
  7. package/template/_claude/rules/global/core.md +6 -0
  8. package/template/client/.dockerignore +63 -0
  9. package/template/client/.env.example.production +5 -0
  10. package/template/client/Dockerfile +98 -0
  11. package/template/client/next.config.ts +1 -0
  12. package/template/client/src/app/error.tsx +1 -1
  13. package/template/client/src/app/globals.css +18 -83
  14. package/template/client/src/app/layout.tsx +1 -1
  15. package/template/client/src/app/page.tsx +10 -3
  16. package/template/client/src/app/providers.tsx +1 -1
  17. package/template/client/src/components/common/ThemeSwitcher.tsx +112 -0
  18. package/template/client/src/components/layout/Header.tsx +1 -1
  19. package/template/client/src/features/auth/components/AuthInitializer.tsx +8 -2
  20. package/template/client/src/features/auth/components/LoginForm.tsx +1 -1
  21. package/template/client/src/features/auth/components/RegisterForm.tsx +1 -1
  22. package/template/client/src/features/auth/services/auth.service.ts +0 -4
  23. package/template/client/src/lib/api/axios.config.ts +1 -1
  24. package/template/client/src/lib/constants/api-endpoints.ts +0 -2
  25. package/template/client/src/styles/themes/electric-indigo.css +90 -0
  26. package/template/client/src/styles/themes/ocean-teal.css +90 -0
  27. package/template/client/src/styles/themes/rose-pink.css +90 -0
  28. package/template/client/src/styles/themes/warm-orange.css +90 -0
  29. package/template/server/.dockerignore +0 -1
  30. package/template/server/.env.example +21 -0
  31. package/template/server/.env.example.production +26 -0
  32. package/template/server/Dockerfile +8 -0
  33. package/template/server/package.json +1 -1
  34. package/template/server/prisma/schema.prisma +0 -1
  35. package/template/server/src/modules/admin/admin.controller.ts +3 -9
  36. package/template/server/src/modules/admin/admin.routes.ts +7 -0
  37. package/template/server/src/modules/admin/admin.schemas.ts +13 -0
  38. package/template/server/src/modules/auth/auth.repo.ts +9 -8
  39. package/template/server/src/server.ts +1 -1
  40. package/template/server/tsconfig.build.json +4 -0
  41. package/template/server/tsconfig.json +1 -0
  42. package/template/server/postman_collection.json +0 -666
@@ -12,6 +12,9 @@ import crypto from 'crypto';
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = path.dirname(__filename);
14
14
 
15
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
16
+ const VERSION = packageJson.version;
17
+
15
18
  const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
16
19
 
17
20
  // Files that contain template variables and need replacement
@@ -126,11 +129,11 @@ async function main() {
126
129
  program
127
130
  .name('create-tigra')
128
131
  .description('Create a production-ready full-stack app with Next.js + Fastify + Prisma + Redis')
129
- .version('2.1.0')
132
+ .version(VERSION)
130
133
  .argument('[project-name]', 'Name for your new project')
131
134
  .action(async (projectNameArg) => {
132
135
  console.log();
133
- console.log(chalk.bold(' Create Tigra') + chalk.dim(' v2.1.0'));
136
+ console.log(chalk.bold(' Create Tigra') + chalk.dim(` v${VERSION}`));
134
137
  console.log();
135
138
 
136
139
  let projectName = projectNameArg;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tigra",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "type": "module",
5
5
  "description": "Create a production-ready full-stack app with Next.js 16 + Fastify 5 + Prisma + Redis",
6
6
  "bin": {
@@ -32,6 +32,12 @@ src/
32
32
  │ ├── store/ # <domain>Slice.ts (if needed)
33
33
  │ ├── types/ # <domain>.types.ts
34
34
  │ └── actions/ # <domain>.actions.ts (Server Actions)
35
+ ├── styles/
36
+ │ └── themes/ # Color theme presets (switch in globals.css import)
37
+ │ ├── warm-orange.css # Default — earthy, warm
38
+ │ ├── electric-indigo.css
39
+ │ ├── ocean-teal.css
40
+ │ └── rose-pink.css
35
41
  ├── hooks/ # Global hooks (useDebounce, useLocalStorage, useMediaQuery)
36
42
  ├── lib/
37
43
  │ ├── api/ # axios.config.ts, api.types.ts
@@ -14,60 +14,83 @@ Clean, airy, "expensive" look inspired by Linear, Vercel, Stripe, Arc. Every vis
14
14
 
15
15
  This project uses **Tailwind CSS v4** with **OKLCH color space** and the `@theme inline` directive (not the legacy `tailwind.config.ts`).
16
16
 
17
+ **Key differences from Tailwind v3:**
18
+ - No `tailwind.config.ts` — all config is CSS-based via `@theme inline`
19
+ - Colors use **OKLCH** (perceptually uniform) not HSL
20
+ - `@custom-variant dark` replaces `darkMode: 'class'`
21
+ - No `@layer base { :root { } }` — variables defined on `:root` via theme preset files
22
+
23
+ ---
24
+
25
+ ## Theme Preset System (Color Management)
26
+
27
+ **ALL color variables live in theme preset files, NOT in `globals.css`.** This is the single source of truth for the entire app's color palette.
28
+
29
+ ### How It Works
30
+
31
+ ```
32
+ src/
33
+ ├── app/globals.css ← imports ONE theme preset (switch here)
34
+ └── styles/themes/
35
+ ├── warm-orange.css ← Earthy, warm (default)
36
+ ├── electric-indigo.css ← Modern, bold, tech-forward
37
+ ├── ocean-teal.css ← Calm, professional
38
+ └── rose-pink.css ← Elegant, creative
39
+ ```
40
+
41
+ `globals.css` imports the active theme via a single line:
42
+
17
43
  ```css
18
- /* app/globals.css */
19
- @import "tailwindcss";
20
- @import "tw-animate-css";
21
- @import "shadcn/tailwind.css";
22
-
23
- @custom-variant dark (&:is(.dark *));
24
-
25
- @theme inline {
26
- --color-background: var(--background);
27
- --color-foreground: var(--foreground);
28
- --font-sans: var(--font-geist-sans);
29
- --font-mono: var(--font-geist-mono);
30
- /* ... maps all semantic tokens to Tailwind */
31
- }
44
+ @import "../styles/themes/warm-orange.css";
45
+ ```
46
+
47
+ **To switch the entire palette**: change that ONE import line. That's it. Every color in the app updates instantly — light mode, dark mode, charts, sidebar, everything.
48
+
49
+ ### Theme Preset Structure
50
+
51
+ Each preset file defines ALL semantic color variables for both `:root` (light) and `.dark` (dark mode):
32
52
 
53
+ ```css
33
54
  :root {
34
55
  --radius: 0.625rem;
35
- --background: oklch(1 0 0);
36
- --foreground: oklch(0.145 0 0);
37
- --primary: oklch(0.45 0.2 260);
38
- --primary-foreground: oklch(0.985 0 0);
39
- --secondary: oklch(0.97 0 0);
40
- --secondary-foreground: oklch(0.205 0 0);
41
- --muted: oklch(0.97 0 0);
42
- --muted-foreground: oklch(0.556 0 0);
43
- --accent: oklch(0.97 0 0);
44
- --accent-foreground: oklch(0.205 0 0);
45
- --destructive: oklch(0.577 0.245 27.325);
46
- --border: oklch(0.922 0 0);
47
- --input: oklch(0.922 0 0);
48
- --ring: oklch(0.45 0.2 260);
49
- --success: oklch(0.52 0.17 155);
50
- --success-foreground: oklch(1 0 0);
51
- --warning: oklch(0.75 0.18 75);
52
- --warning-foreground: oklch(0.2 0 0);
53
- --info: oklch(0.55 0.15 240);
54
- --info-foreground: oklch(1 0 0);
55
- --chart-1 through --chart-5 /* Data visualization colors */
56
- --sidebar, --sidebar-foreground, etc. /* Sidebar-specific tokens */
56
+ --background: oklch(...);
57
+ --foreground: oklch(...);
58
+ --primary: oklch(...);
59
+ --primary-foreground: oklch(...);
60
+ /* ... all ~35 semantic tokens */
57
61
  }
58
62
 
59
63
  .dark {
60
- --background: oklch(0.145 0 0);
61
- --foreground: oklch(0.985 0 0);
64
+ --background: oklch(...);
65
+ --foreground: oklch(...);
66
+ --primary: oklch(...);
62
67
  /* ... dark mode overrides for all tokens */
63
68
  }
64
69
  ```
65
70
 
66
- **Key differences from Tailwind v3:**
67
- - No `tailwind.config.ts` — all config is CSS-based via `@theme inline`
68
- - Colors use **OKLCH** (perceptually uniform) not HSL
69
- - `@custom-variant dark` replaces `darkMode: 'class'`
70
- - No `@layer base { :root { } }` — variables defined directly on `:root`
71
+ ### Creating a Custom Theme
72
+
73
+ 1. Copy any existing preset file (e.g., `warm-orange.css`)
74
+ 2. Rename it (e.g., `my-brand.css`)
75
+ 3. Edit the OKLCH values to match your brand palette
76
+ 4. Update the import in `globals.css`: `@import "../styles/themes/my-brand.css";`
77
+
78
+ ### Available Presets
79
+
80
+ | Preset | Accent | Vibe | Inspired by |
81
+ |--------|--------|------|-------------|
82
+ | `warm-orange.css` | Terracotta orange | Earthy, warm, approachable | Claude |
83
+ | `electric-indigo.css` | Deep indigo-violet | Modern, bold, tech-forward | Linear, Figma |
84
+ | `ocean-teal.css` | Deep teal-cyan | Calm, professional, trustworthy | Stripe, Vercel |
85
+ | `rose-pink.css` | Soft rose-magenta | Elegant, creative, premium | Dribbble, Notion |
86
+
87
+ ### CRITICAL RULES — Color Management
88
+
89
+ 1. **NEVER add or modify color variables directly in `globals.css`.** All `:root` and `.dark` color variables belong in the active theme preset file only.
90
+ 2. **NEVER hardcode OKLCH/hex/rgb values in components.** Always use semantic tokens (`bg-primary`, `text-foreground`).
91
+ 3. **To change the brand palette**: switch the import in `globals.css` or edit the active preset file. Never scatter color values across multiple files.
92
+ 4. **New semantic tokens**: If you need a new color token (rare), add it to ALL preset files to keep them in sync.
93
+ 5. **The `@theme inline` block in `globals.css` maps CSS vars to Tailwind** — it does NOT define colors. Colors come from the preset.
71
94
 
72
95
  ---
73
96
 
@@ -117,7 +140,7 @@ This project uses **Tailwind CSS v4** with **OKLCH color space** and the `@theme
117
140
  1. **Never hardcode**: No `bg-blue-500`, no `bg-[#3b82f6]`, no `style={{ color }}`. Always semantic tokens.
118
141
  2. **Semantic names by purpose**: `bg-destructive` not `bg-red`.
119
142
  3. **Always pair bg + foreground**: `bg-primary text-primary-foreground` for contrast.
120
- 4. **Single source of truth**: Change colors only in `globals.css` variables.
143
+ 4. **Single source of truth**: Change colors ONLY in the active theme preset file (`src/styles/themes/*.css`). Never in `globals.css`, never in components.
121
144
  5. **90% monochrome**: 90% of UI uses `background`, `foreground`, `muted`, `border`. Color is the exception.
122
145
  6. **Opacity for hierarchy**: Use `bg-primary/10`, `bg-primary/5` for tinted backgrounds.
123
146
 
@@ -9,7 +9,7 @@
9
9
  | Creating files, folders, feature modules | `01-project-structure.md` |
10
10
  | Building components, writing types/interfaces | `02-components-and-types.md` |
11
11
  | Fetching data, managing state, calling APIs, forms | `03-data-and-state.md` |
12
- | Choosing colors, styling, typography, spacing, motion | `04-design-system.md` |
12
+ | Choosing colors, styling, typography, spacing, motion, **theme presets** | `04-design-system.md` |
13
13
  | Auth tokens, env vars, security headers | `05-security.md` |
14
14
  | UX psychology, cognitive load, a11y, performance | `06-ux-checklist.md` |
15
15
 
@@ -36,8 +36,9 @@ State: Server data (SSR) → Server Components
36
36
  1. **Mobile-first**: All Tailwind classes start at mobile. Desktop is the enhancement (`md:`, `lg:`). Touch targets min 44x44px. No functionality behind hover-only states.
37
37
  2. **Server Components by default.** Only add `'use client'` when you need hooks, state, or event handlers.
38
38
  3. **Component limits**: Max 250 lines, max 5 props, max 3 JSX nesting levels.
39
- 4. **No hardcoded colors**: Use Tailwind semantic tokens (`bg-primary`, `text-foreground`). Never hex/rgb.
39
+ 4. **No hardcoded colors**: Use Tailwind semantic tokens (`bg-primary`, `text-foreground`). Never hex/rgb. **All color variables live in theme preset files (`src/styles/themes/*.css`), NOT in `globals.css` or components.** To change the palette, switch the import in `globals.css` or edit the active preset. Read `04-design-system.md` → "Theme Preset System" for details.
40
40
  5. **No inline styles**: Tailwind only. Use `cn()` for conditional classes.
41
41
  6. **Import order**: React/Next → third-party → UI → local → hooks → services → types → utils.
42
42
  7. **Forms**: Validate with Zod. Always validate client-side AND server-side.
43
43
  8. **Security**: Never inject raw HTML without sanitization. Never prefix secrets with `NEXT_PUBLIC_`.
44
+ 9. **Deployment**: Never remove `output: "standalone"` from `next.config.ts`. When adding `NEXT_PUBLIC_*` env vars, also add them as `ARG` + `ENV` in the Dockerfile builder stage. Read `07-deployment.md` for details.
@@ -0,0 +1,178 @@
1
+ > **SCOPE**: These rules apply to the **entire workspace** (server + client). Always active.
2
+
3
+ # Task Completion Reports
4
+
5
+ When you finish a task, phase, or multi-step implementation, you MUST provide a structured completion report. Freeform paragraphs like "Fixed issues and completed remaining tasks" are not acceptable. The report must give the user a clear, scannable picture of everything that changed, why, and what to do next.
6
+
7
+ ---
8
+
9
+ ## When to Report
10
+
11
+ | Situation | Report required? |
12
+ |-----------|-----------------|
13
+ | Completed a full task or feature | **Yes — Full Report** |
14
+ | Completed a phase in a multi-phase plan | **Yes — Phase Report** (subset of Full Report) |
15
+ | Fixed a bug | **Yes — Bug Fix Report** |
16
+ | Small config change, typo fix, single-file edit | **No** — a 1-2 sentence explanation is fine |
17
+
18
+ ---
19
+
20
+ ## Full Report Template
21
+
22
+ Use this structure after completing a feature or multi-phase task. Omit sections that don't apply (e.g., skip "Database Changes" if no migrations were created), but never omit "Files Changed" or "How to Test".
23
+
24
+ ```
25
+ ## Summary
26
+ [1-3 sentences: what was built/changed and why]
27
+
28
+ ## Files Changed
29
+
30
+ ### Created
31
+ - `path/to/file.ts` — [purpose: what this file does]
32
+
33
+ ### Modified
34
+ - `path/to/file.ts` — [what changed and why]
35
+
36
+ ### Deleted
37
+ - `path/to/file.ts` — [why it was removed]
38
+
39
+ ## New API Endpoints (if applicable)
40
+ | Method | Path | Auth | Description |
41
+ |--------|------|------|-------------|
42
+
43
+ ## Database Changes (if applicable)
44
+ - Migration: `YYYYMMDD_name` — [what it does]
45
+ - New tables: [list]
46
+ - Modified tables: [what changed]
47
+ - Indexes added: [list]
48
+
49
+ ## Environment Variables (if applicable)
50
+ | Variable | Required | Where | Description |
51
+ |----------|----------|-------|-------------|
52
+ [Where = .env / .env.example / Dockerfile ARG / Coolify]
53
+
54
+ ## Dependencies Added (if applicable)
55
+ | Package | Purpose |
56
+ |---------|---------|
57
+ - Note if any require system-level installs (apk add)
58
+
59
+ ## Key Decisions & Trade-offs
60
+ [Explain non-obvious choices. Why was approach A chosen over B? What assumptions were made? What are the limitations?]
61
+
62
+ ## Deployment & Production Impact (if applicable)
63
+ [This section is REQUIRED whenever changes affect deployment, infrastructure, or production behavior. Include ALL that apply:]
64
+
65
+ ### Dockerfile Changes
66
+ - [New ARG/ENV added, new COPY lines, new apk packages, port changes, etc.]
67
+
68
+ ### Environment / Coolify Configuration
69
+ - [New env vars that must be set in Coolify/hosting platform]
70
+ - [Build arguments that must be added]
71
+ - [Volume mounts needed]
72
+
73
+ ### Database Migration Required
74
+ - [Migration name and what it does]
75
+ - [Must run `prisma migrate deploy` before/after deploying]
76
+ - [Any data migration or backfill needed]
77
+
78
+ ### Infrastructure Changes
79
+ - [New external services required (Redis, S3, third-party APIs)]
80
+ - [DNS/domain changes needed]
81
+ - [SSL/certificate changes]
82
+ - [New cron jobs or background workers]
83
+
84
+ ### Deployment Order
85
+ - [If server and client must be deployed in a specific order, state it]
86
+ - [If a migration must run before the new code deploys, state it]
87
+
88
+ ### Rollback Plan
89
+ - [What happens if this deployment fails — is it safe to roll back?]
90
+ - [Are the database changes backwards-compatible with the previous code version?]
91
+
92
+ ## Breaking Changes (if any)
93
+ - [What breaks, what to update, and how]
94
+
95
+ ## Manual Steps Required
96
+ 1. [Ordered list of things the user must do before this works]
97
+ - e.g., "Add GEMINI_API_KEY to .env"
98
+ - e.g., "Run npm run prisma:migrate dev"
99
+
100
+ ## How to Test
101
+ 1. [Step-by-step verification the user can follow]
102
+ - Be specific: exact commands, exact Postman steps, exact URLs
103
+ - Include expected responses where helpful
104
+
105
+ ## Known Limitations / TODOs (if any)
106
+ - [Things not yet implemented, edge cases not handled, future improvements needed]
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Phase Report Template
112
+
113
+ Use this when completing one phase of a multi-phase plan. Shorter than a Full Report but still structured.
114
+
115
+ ```
116
+ ## Phase N Complete: [Phase Title]
117
+
118
+ ### What was done
119
+ - [Bullet list of concrete changes]
120
+
121
+ ### Files Changed
122
+ - `path/to/file.ts` — [what and why]
123
+
124
+ ### Key Decisions
125
+ - [Any non-obvious choices made during this phase]
126
+
127
+ ### Blockers or Concerns
128
+ - [Anything that might affect subsequent phases]
129
+
130
+ ### Phase Status
131
+ - [x] Phase N complete
132
+ - [ ] Phase N+1: [title] — next
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Bug Fix Report Template
138
+
139
+ ```
140
+ ## Bug Fix: [Short description]
141
+
142
+ ### Root Cause
143
+ [What was actually wrong — not just the symptom, but the underlying cause]
144
+
145
+ ### Fix Applied
146
+ - `path/to/file.ts` — [what changed]
147
+
148
+ ### Why This Fix
149
+ [Why this approach was chosen. What other approaches were considered and rejected.]
150
+
151
+ ### How to Verify
152
+ 1. [Steps to confirm the fix works]
153
+
154
+ ### Regression Risk
155
+ - [Could this fix break anything else? What was checked?]
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Rules
161
+
162
+ 1. **Structure over prose.** Use the templates above. Tables, bullet points, and headers — not paragraphs.
163
+ 2. **Every file gets a "why".** Don't just list `file.ts` — explain what changed and why. "Added creditBalance: 0 to mocks" → "Added `creditBalance: 0` to user mocks in `setup.ts` because the new credits module added this required field to the User model, and existing test fixtures would fail validation without it."
164
+ 3. **Be specific in "How to Test".** Not "use Postman to test." Instead: "1. POST `{{baseUrl}}/auth/login` with test credentials. 2. POST `{{baseUrl}}/generations` with body `{ templateId: '...', image: <file> }`. 3. Expected: 201 with `{ success: true, data: { id, status: 'pending' } }`."
165
+ 4. **Explain decisions, not just actions.** "Used upsert for seed data" → "Used `upsert` instead of `create` for seed data so the seed script is idempotent — running it twice won't throw duplicate key errors."
166
+ 5. **Surface what the user needs to do.** If the user must add an env var, run a migration, install something, or restart a service — put it in "Manual Steps Required" prominently. Don't bury it in a paragraph.
167
+ 6. **Honest about limitations.** If something is incomplete, has edge cases, or needs future work — say so in "Known Limitations." Don't pretend everything is perfect.
168
+ 7. **Scale to the task.** A 5-phase feature gets a full report with every section. A single service method gets a shorter report. Use judgment, but always use the structured format.
169
+ 8. **Deployment impact is never optional.** If ANY of the following changed, the "Deployment & Production Impact" section is REQUIRED — no exceptions:
170
+ - New or modified environment variables
171
+ - New npm packages with native dependencies
172
+ - Database schema changes (new tables, columns, indexes)
173
+ - Dockerfile modifications needed
174
+ - New external service dependencies (APIs, Redis, S3, etc.)
175
+ - Port, entry point, or health check changes
176
+ - File upload/storage changes requiring volume mounts
177
+ - Changes to build process or build arguments
178
+ If none of these apply, explicitly state: "No deployment impact — no infrastructure, env, or database changes."
@@ -66,6 +66,12 @@ When the user asks to create, scaffold, or start a new server or client project,
66
66
 
67
67
  ---
68
68
 
69
+ ## Task Completion Reports
70
+
71
+ After completing any task, phase, or bug fix, you MUST provide a structured completion report — not freeform paragraphs. **Read `completion-reports.md`** for the required templates and rules. This includes deployment/production impact analysis whenever infrastructure, env vars, database, or Docker changes are involved.
72
+
73
+ ---
74
+
69
75
  ## Code Review Checklist
70
76
 
71
77
  Before considering work done, verify:
@@ -0,0 +1,63 @@
1
+ # Dependencies (will be installed fresh in Docker)
2
+ node_modules
3
+ npm-debug.log*
4
+ yarn-debug.log*
5
+ yarn-error.log*
6
+ pnpm-debug.log*
7
+
8
+ # Build output (will be built fresh in Docker)
9
+ .next
10
+ out
11
+ *.tsbuildinfo
12
+
13
+ # Environment files (use Docker env vars instead)
14
+ .env
15
+ .env.local
16
+ .env.*.local
17
+ .env.development
18
+ .env.test
19
+
20
+ # Git
21
+ .git
22
+ .gitignore
23
+ .gitattributes
24
+
25
+ # IDE
26
+ .vscode
27
+ .idea
28
+ *.swp
29
+ *.swo
30
+ *~
31
+ .DS_Store
32
+
33
+ # Testing
34
+ coverage
35
+ .nyc_output
36
+ **/__tests__
37
+ **/*.test.ts
38
+ **/*.test.tsx
39
+ **/*.spec.ts
40
+ **/*.spec.tsx
41
+ vitest.config.ts
42
+ jest.config.ts
43
+
44
+ # Documentation
45
+ docs
46
+ CHANGELOG.md
47
+ LICENSE
48
+
49
+ # Docker
50
+ Dockerfile
51
+ .dockerignore
52
+ docker-compose.yml
53
+
54
+ # CI/CD
55
+ .github
56
+ .gitlab-ci.yml
57
+ .circleci
58
+
59
+ # Misc
60
+ .prettierrc
61
+ .eslintrc
62
+ .eslintignore
63
+ .editorconfig
@@ -0,0 +1,5 @@
1
+ # Public API URL - points to the production server's base URL
2
+ NEXT_PUBLIC_API_BASE_URL=https://api.yourdomain.com/api/v1
3
+
4
+ # App name displayed in the UI
5
+ NEXT_PUBLIC_APP_NAME={{PROJECT_DISPLAY_NAME}}
@@ -0,0 +1,98 @@
1
+ # ===================================================================
2
+ # Multi-stage Dockerfile for Next.js Production Deployment
3
+ # Optimized for Coolify, Docker Compose, and Kubernetes
4
+ # Requires `output: "standalone"` in next.config.ts
5
+ # ===================================================================
6
+
7
+ # ===================================================================
8
+ # Stage 1: Dependencies (cached layer)
9
+ # ===================================================================
10
+ FROM node:20-alpine AS dependencies
11
+
12
+ WORKDIR /app
13
+
14
+ # Copy package files
15
+ COPY package.json package-lock.json* pnpm-lock.yaml* yarn.lock* ./
16
+
17
+ # Install dependencies (use the lockfile that exists)
18
+ RUN if [ -f pnpm-lock.yaml ]; then \
19
+ npm install -g pnpm && pnpm install --frozen-lockfile; \
20
+ elif [ -f yarn.lock ]; then \
21
+ yarn install --frozen-lockfile; \
22
+ else \
23
+ npm ci; \
24
+ fi
25
+
26
+ # ===================================================================
27
+ # Stage 2: Build (compile Next.js)
28
+ # ===================================================================
29
+ FROM node:20-alpine AS builder
30
+
31
+ WORKDIR /app
32
+
33
+ # Copy dependencies from previous stage
34
+ COPY --from=dependencies /app/node_modules ./node_modules
35
+
36
+ # Copy source code
37
+ COPY . .
38
+
39
+ # Build arguments for env vars needed at build time
40
+ # Next.js inlines NEXT_PUBLIC_* values during build, so they must
41
+ # be available here. Pass them via --build-arg in Coolify/Docker.
42
+ ARG NEXT_PUBLIC_API_BASE_URL
43
+ ARG NEXT_PUBLIC_APP_NAME
44
+
45
+ ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
46
+ ENV NEXT_PUBLIC_APP_NAME=$NEXT_PUBLIC_APP_NAME
47
+
48
+ # Disable Next.js telemetry during build
49
+ ENV NEXT_TELEMETRY_DISABLED=1
50
+
51
+ # Build the application (outputs to .next/standalone)
52
+ RUN npm run build
53
+
54
+ # ===================================================================
55
+ # Stage 3: Production Runtime
56
+ # ===================================================================
57
+ FROM node:20-alpine AS production
58
+
59
+ # Install dumb-init for proper signal handling
60
+ RUN apk add --no-cache dumb-init
61
+
62
+ # Create non-root user for security
63
+ RUN addgroup -g 1001 -S nodejs && \
64
+ adduser -S nextjs -u 1001
65
+
66
+ WORKDIR /app
67
+
68
+ # Copy the standalone server (includes only required node_modules)
69
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
70
+
71
+ # Copy static assets (not included in standalone output)
72
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
73
+
74
+ # Copy public folder (favicon, images, etc.)
75
+ COPY --from=builder --chown=nextjs:nodejs /app/public ./public
76
+
77
+ # Switch to non-root user
78
+ USER nextjs
79
+
80
+ # Disable telemetry at runtime
81
+ ENV NEXT_TELEMETRY_DISABLED=1
82
+
83
+ # Set hostname to listen on all interfaces (required in containers)
84
+ ENV HOSTNAME="0.0.0.0"
85
+
86
+ # Default port (override via PORT env var in Coolify)
87
+ ENV PORT=3000
88
+ EXPOSE 3000
89
+
90
+ # Health check for container orchestration
91
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
92
+ CMD node -e "const p=process.env.PORT||3000;require('http').get('http://localhost:'+p,(r)=>{process.exit(r.statusCode===200?0:1)})"
93
+
94
+ # Use dumb-init to handle signals properly
95
+ ENTRYPOINT ["dumb-init", "--"]
96
+
97
+ # Start the standalone Next.js server
98
+ CMD ["node", "server.js"]
@@ -10,6 +10,7 @@ const apiOrigin = (() => {
10
10
  })();
11
11
 
12
12
  const nextConfig: NextConfig = {
13
+ output: "standalone",
13
14
  async headers() {
14
15
  return [
15
16
  {
@@ -13,7 +13,7 @@ export default function GlobalError({
13
13
  reset: () => void;
14
14
  }): React.ReactElement {
15
15
  return (
16
- <div className="flex min-h-[400px] flex-col items-center justify-center p-8 text-center">
16
+ <div className="flex min-h-dvh flex-col items-center justify-center p-8 text-center">
17
17
  <AlertCircle className="mb-4 h-12 w-12 text-destructive" />
18
18
  <h2 className="mb-2 text-2xl font-bold">Something went wrong</h2>
19
19
  <p className="mb-4 text-muted-foreground">