create-tigra 2.8.0 → 3.0.2

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 (53) hide show
  1. package/README.md +10 -3
  2. package/bin/create-tigra.js +77 -37
  3. package/package.json +5 -5
  4. package/template/_claude/commands/create-server.md +8 -2
  5. package/template/_claude/rules/client/01-project-structure.md +12 -0
  6. package/template/_claude/rules/client/03-data-and-state.md +1 -1
  7. package/template/_claude/rules/client/04-design-system.md +23 -0
  8. package/template/_claude/rules/client/07-deployment.md +99 -0
  9. package/template/_claude/rules/client/08-lockfile-cross-platform.md +79 -0
  10. package/template/_claude/rules/client/core.md +1 -0
  11. package/template/_claude/rules/global/core.md +20 -1
  12. package/template/_claude/rules/global/investigation-before-conclusions.md +57 -0
  13. package/template/_claude/rules/server/core.md +2 -0
  14. package/template/_claude/rules/server/deployment.md +78 -0
  15. package/template/client/next.config.ts +12 -2
  16. package/template/client/package-lock.json +12345 -0
  17. package/template/client/package.json +3 -2
  18. package/template/client/src/components/common/SafeImage.tsx +2 -1
  19. package/template/client/src/lib/api/axios.config.ts +19 -4
  20. package/template/client/src/middleware.ts +7 -0
  21. package/template/gitignore +1 -0
  22. package/template/server/.env.example +248 -194
  23. package/template/server/.env.example.production +221 -168
  24. package/template/server/Dockerfile +29 -5
  25. package/template/server/docker-compose.yml +32 -4
  26. package/template/server/package-lock.json +6544 -6823
  27. package/template/server/package.json +76 -75
  28. package/template/server/prisma/seed.ts +20 -4
  29. package/template/server/src/app.ts +316 -271
  30. package/template/server/src/config/env.ts +150 -99
  31. package/template/server/src/config/rate-limit.config.ts +16 -0
  32. package/template/server/src/libs/__tests__/auth-path.test.ts +24 -0
  33. package/template/server/src/libs/__tests__/client-ip.test.ts +121 -0
  34. package/template/server/src/libs/__tests__/http.test.ts +23 -9
  35. package/template/server/src/libs/__tests__/ip-block.test.ts +62 -0
  36. package/template/server/src/libs/__tests__/origin-check.test.ts +53 -0
  37. package/template/server/src/libs/__tests__/url-safety.test.ts +80 -0
  38. package/template/server/src/libs/auth-path.ts +14 -0
  39. package/template/server/src/libs/auth.ts +6 -16
  40. package/template/server/src/libs/client-ip.ts +77 -0
  41. package/template/server/src/libs/cookies.ts +1 -1
  42. package/template/server/src/libs/duration.ts +30 -0
  43. package/template/server/src/libs/ip-block.ts +220 -206
  44. package/template/server/src/libs/origin-check.ts +38 -0
  45. package/template/server/src/libs/query-counter.ts +59 -0
  46. package/template/server/src/libs/redis.ts +1 -1
  47. package/template/server/src/libs/url-safety.ts +121 -0
  48. package/template/server/src/modules/auth/__tests__/auth.service.test.ts +274 -44
  49. package/template/server/src/modules/auth/auth.controller.ts +128 -127
  50. package/template/server/src/modules/auth/auth.repo.ts +2 -0
  51. package/template/server/src/modules/auth/auth.service.ts +103 -12
  52. package/template/server/src/test/setup.ts +22 -2
  53. package/template/server/vitest.config.ts +43 -43
@@ -0,0 +1,78 @@
1
+ > **SCOPE**: These rules apply specifically to the **server** directory.
2
+
3
+ # Deployment & Docker
4
+
5
+ This project is deployed via **Docker** on **Coolify** (or any Docker-based platform). The `Dockerfile` is the production deployment contract. Every code change must remain compatible with it.
6
+
7
+ ---
8
+
9
+ ## Dockerfile Architecture
10
+
11
+ The server uses a **3-stage multi-stage build**:
12
+
13
+ ```
14
+ Stage 1 (dependencies) → Installs prod-only node_modules (cached layer)
15
+ Stage 2 (builder) → Installs all deps, generates Prisma client, compiles TypeScript
16
+ Stage 3 (production) → Alpine + dumb-init, non-root user, copies dist + prod node_modules + Prisma
17
+ ```
18
+
19
+ **Entry point**: the container `CMD` runs `npx prisma migrate deploy` and then starts `node dist/server.js` — pending migrations are applied automatically on every container boot (migrate-on-boot).
20
+ **Health check**: `GET /api/v1/live` — this endpoint MUST always exist and return 200.
21
+
22
+ ---
23
+
24
+ ## When to Update the Dockerfile
25
+
26
+ | You did this... | Update Dockerfile? | What to change |
27
+ |---|---|---|
28
+ | Added a new npm dependency | No | Automatic — `npm ci` installs from `package.json` |
29
+ | Added a native/system dependency (e.g., `sharp`, `bcrypt`) | **Yes** | Add `apk add` in the production stage for required system libraries |
30
+ | Changed the build command or output directory | **Yes** | Update the `RUN npm run build` or `COPY` paths in stage 2/3 |
31
+ | Changed the entry point file (e.g., renamed `server.ts`) | **Yes** | Update the `CMD` to run `dist/<new-name>.js` (keep the `prisma migrate deploy` step before it) |
32
+ | Changed the default port | **Yes** | Update `EXPOSE` and the `HEALTHCHECK` port |
33
+ | Added/renamed a health check endpoint | **Yes** | Update the `HEALTHCHECK` URL path |
34
+ | Added files needed at runtime (e.g., templates, static assets) | **Yes** | Add a `COPY` line in stage 3 |
35
+ | Changed Prisma schema | No | Automatic — `npx prisma generate` runs in stage 2 |
36
+ | Added a new env var | Maybe | If it's needed at **build time**, add `ARG` + `ENV` in the builder stage |
37
+ | Added file upload functionality | **Yes** | Add a `VOLUME` directive or ensure the upload directory is writable |
38
+
39
+ ---
40
+
41
+ ## Critical Rules
42
+
43
+ 1. **Health endpoint is sacred.** The route `GET /api/v1/live` must always exist and return HTTP 200. Coolify, Docker, and load balancers use it to determine if the container is alive. Never remove, rename, or gate it behind auth.
44
+
45
+ 2. **Never break the build chain.** If you rename the build output directory, the entry file, or change `tsconfig.json` `outDir`, update the Dockerfile `COPY` paths and `CMD` accordingly.
46
+
47
+ 3. **System dependencies must be explicit.** If a new npm package requires native binaries (e.g., `sharp` needs `libvips`, `bcrypt` needs `build-base`), add `apk add --no-cache <package>` in the production stage. The build will succeed locally but fail in Docker without this.
48
+
49
+ 4. **Non-root user.** The app runs as `nodejs:nodejs` (UID 1001). Any files the app needs to write (uploads, logs) must be in directories owned by this user. Add `RUN mkdir -p /app/<dir> && chown nodejs:nodejs /app/<dir>` if needed.
50
+
51
+ 5. **No secrets in the image.** Environment variables are injected at runtime via Coolify/Docker. Never hardcode secrets, never `COPY .env`, never use `ENV` for sensitive values. Only use `ARG`/`ENV` for non-secret build-time config.
52
+
53
+ 6. **Keep `.dockerignore` in sync.** When adding new directories or file types that should NOT be in the Docker build context (test fixtures, docs, local scripts), add them to `.dockerignore`. When adding files that ARE needed at build time, make sure they're not ignored.
54
+
55
+ 7. **Port consistency.** The default port is `8000`. If you change the port in `src/config/env.ts`, also update `EXPOSE` and the `HEALTHCHECK` in the Dockerfile.
56
+
57
+ ---
58
+
59
+ ## Coolify-Specific Notes
60
+
61
+ - **Environment variables**: Set in Coolify's UI, injected at container runtime. No `.env` file needed.
62
+ - **Build arguments**: For build-time vars, use Coolify's "Build Arguments" section → maps to `docker build --build-arg`.
63
+ - **Persistent storage**: For file uploads, mount a volume in Coolify to `/app/uploads`. Add to Dockerfile: `RUN mkdir -p /app/uploads && chown nodejs:nodejs /app/uploads` before `USER nodejs`.
64
+ - **Database migrations**: Applied automatically at container startup — the Dockerfile `CMD` runs `npx prisma migrate deploy` before starting the server, so no Coolify configuration is needed. (Alternative: remove the migrate step from the `CMD` and run `npx prisma migrate deploy` as a pre-deploy command in Coolify instead.)
65
+
66
+ ---
67
+
68
+ ## Files That Matter for Deployment
69
+
70
+ | File | Purpose | Must exist? |
71
+ |---|---|---|
72
+ | `Dockerfile` | Production build instructions | Yes |
73
+ | `.dockerignore` | Excludes files from Docker build context | Yes |
74
+ | `package.json` | Dependencies and build script | Yes |
75
+ | `tsconfig.json` | TypeScript compilation config | Yes |
76
+ | `prisma/schema.prisma` | Database schema (copied to runtime) | Yes |
77
+ | `prisma/migrations/` | Migration files (copied to runtime) | Yes |
78
+ | `src/server.ts` | Entry point (compiled to `dist/server.js`) | Yes |
@@ -9,10 +9,20 @@ const apiOrigin = (() => {
9
9
  }
10
10
  })();
11
11
 
12
+ // 'unsafe-eval' is required by Next.js dev mode (HMR/react-refresh) but must
13
+ // NOT ship to production. 'unsafe-inline' stays in both modes — the Next.js
14
+ // inline runtime requires it unless a full nonce infrastructure is added.
15
+ const isDev = process.env.NODE_ENV === "development";
16
+ const scriptSrc = `script-src 'self'${isDev ? " 'unsafe-eval'" : ""} 'unsafe-inline'`;
17
+
12
18
  const nextConfig: NextConfig = {
13
19
  output: "standalone",
14
20
  experimental: {
15
- staleTimes: { dynamic: 0, static: 0 },
21
+ // Next 16.2+ rejects staleTimes.static below 30 (config schema enforces gte(30));
22
+ // an invalid value is ignored entirely, silently re-enabling the Router Cache.
23
+ // 30s is the closest allowed to "never serve stale RSC payloads on back-navigation".
24
+ // dynamic: 0 (still unconstrained) is what protects data pages — never raise it.
25
+ staleTimes: { dynamic: 0, static: 30 },
16
26
  },
17
27
  async headers() {
18
28
  return [
@@ -27,7 +37,7 @@ const nextConfig: NextConfig = {
27
37
  key: "Content-Security-Policy",
28
38
  value: [
29
39
  "default-src 'self'",
30
- "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
40
+ scriptSrc,
31
41
  "style-src 'self' 'unsafe-inline'",
32
42
  `img-src 'self' blob: data: https: ${apiOrigin}`,
33
43
  "font-src 'self'",