@next-friday/create-app 2.1.7 → 2.1.8

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/README.md CHANGED
@@ -65,7 +65,7 @@ The name must:
65
65
  ## What the CLI does
66
66
 
67
67
  1. Copies the template into the project directory and replaces the template's package name with the project name.
68
- 2. Writes `.env` from `.env.example`. For Payload, it sets `PAYLOAD_SECRET` to a random secret.
68
+ 2. Writes `.env` from `.env.example`. For Payload and Turborepo, it sets `PAYLOAD_SECRET` to a random secret.
69
69
  3. Runs `git init --initial-branch=main`, unless the directory is already in a Git repository.
70
70
  4. Runs `pnpm install`, which also installs the Git hooks.
71
71
  5. Prints the next steps, for example:
@@ -75,7 +75,7 @@ The name must:
75
75
  pnpm start:dev
76
76
  ```
77
77
 
78
- The development script is `pnpm dev` for Next.js and Payload, and `pnpm start:dev` for Node.js and NestJS.
78
+ The development script is `pnpm dev` for Next.js, Payload, and Turborepo, and `pnpm start:dev` for Node.js and NestJS.
79
79
 
80
80
  Then follow **After creating a project from this template** in the project's `README.md` to make the first commit and set up the repository.
81
81
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-friday/create-app",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "Create a Next Friday project from a template.",
5
5
  "keywords": [
6
6
  "create",
@@ -49,7 +49,7 @@
49
49
  ]
50
50
  },
51
51
  {
52
- "matcher": "Bash",
52
+ "matcher": "Bash|PowerShell|Monitor",
53
53
  "hooks": [
54
54
  {
55
55
  "type": "command",
@@ -33,6 +33,7 @@ concurrency:
33
33
  jobs:
34
34
  verify:
35
35
  name: Verify the requested commit
36
+ if: github.ref == 'refs/heads/main'
36
37
  runs-on: ubuntu-latest
37
38
  timeout-minutes: 5
38
39
  permissions:
@@ -66,13 +67,14 @@ jobs:
66
67
  prod)
67
68
  previous=uat
68
69
  export EXPECTED_TITLE="Deploy $COMMIT_SHA to uat"
69
- deployed="$(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?event=workflow_dispatch&status=success&per_page=100" --jq '.workflow_runs[] | select(.display_title == env.EXPECTED_TITLE) | .id' | wc -l)"
70
+ deployed="$(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?event=workflow_dispatch&status=success&branch=main&per_page=100" --jq '.workflow_runs[] | select(.display_title == env.EXPECTED_TITLE) | .id' | wc -l)"
70
71
  ;;
71
72
  esac
72
73
  [[ "$deployed" -gt 0 ]] || { echo "::error::$COMMIT_SHA has no successful $previous deployment; promote through $previous first"; exit 1; }
73
74
 
74
75
  deploy:
75
76
  name: Deploy to ${{ inputs.environment }}
77
+ if: github.ref == 'refs/heads/main'
76
78
  needs: verify
77
79
  runs-on: ubuntu-latest
78
80
  timeout-minutes: 30
@@ -28,7 +28,7 @@ NestJS HTTP API in TypeScript on pnpm and Node.js `>=24.15.0 <25`.
28
28
 
29
29
  ## Known pitfalls
30
30
 
31
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that names a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`, even when it only reads.
31
+ - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
32
32
 
33
33
  ## Related documentation
34
34
 
@@ -68,7 +68,7 @@ On Vercel, the zero-configuration NestJS preset takes precedence over the `Docke
68
68
  - the `RAILWAY_SERVICE` variable: the service name;
69
69
  - the `APP_URL` variable: the public `https://` URL.
70
70
 
71
- Limit `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
71
+ Limit `dev`, `uat`, and `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
72
72
 
73
73
  3. Set the repository variable `DEPLOY_ENABLED` to `true`. Each push to `main` that passes CI then deploys to `dev`.
74
74
  4. Promote with **Actions → Deploy → Run workflow**, giving the environment and the full commit SHA. The workflow requires a successful CI run on `main` for that commit and a successful deployment to the previous environment, then waits for `/health`.
@@ -29,7 +29,7 @@ Next.js App Router web app with React and Tailwind CSS, in TypeScript on pnpm an
29
29
  ## Known pitfalls
30
30
 
31
31
  - **First end-to-end run**: run `pnpm exec playwright install chromium` once. `pnpm test:e2e` starts the development server unless one is already running.
32
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that names a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`, even when it only reads.
32
+ - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
33
33
 
34
34
  ## Related documentation
35
35
 
@@ -64,7 +64,7 @@ On Vercel, deploy without the image; the Next.js preset takes precedence over th
64
64
  - the `RAILWAY_SERVICE` variable: the service name;
65
65
  - the `APP_URL` variable: the public `https://` URL.
66
66
 
67
- Limit `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
67
+ Limit `dev`, `uat`, and `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
68
68
 
69
69
  3. Set the repository variable `DEPLOY_ENABLED` to `true`. Each push to `main` that passes CI then deploys to `dev`.
70
70
  4. Promote with **Actions → Deploy → Run workflow**, giving the environment and the full commit SHA. The workflow requires a successful CI run on `main` for that commit and a successful deployment to the previous environment, then waits for `/health`.
@@ -26,7 +26,7 @@ TypeScript HTTP service on `node:http`, without a framework, on pnpm and Node.js
26
26
 
27
27
  ## Known pitfalls
28
28
 
29
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that names a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`, even when it only reads.
29
+ - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
30
30
 
31
31
  ## Related documentation
32
32
 
@@ -64,7 +64,7 @@ docker run --env PORT=3000 --publish 3000:3000 app
64
64
  - the `RAILWAY_SERVICE` variable: the service name;
65
65
  - the `APP_URL` variable: the public `https://` URL.
66
66
 
67
- Limit `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
67
+ Limit `dev`, `uat`, and `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
68
68
 
69
69
  3. Set the repository variable `DEPLOY_ENABLED` to `true`. Each push to `main` that passes CI then deploys to `dev`.
70
70
  4. Promote with **Actions → Deploy → Run workflow**, giving the environment and the full commit SHA. The workflow requires a successful CI run on `main` for that commit and a successful deployment to the previous environment, then waits for `/health`.
@@ -32,7 +32,7 @@ Payload CMS on Next.js App Router and PostgreSQL, in TypeScript on pnpm and Node
32
32
  ## Known pitfalls
33
33
 
34
34
  - **Database for `pnpm dev` and end-to-end tests**: both need a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`; the README lists every variable. Run `pnpm exec playwright install chromium` once before the first `pnpm test:e2e`.
35
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that names a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`, even when it only reads.
35
+ - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
36
36
 
37
37
  ## Related documentation
38
38
 
@@ -88,7 +88,7 @@ On Vercel, deploy without the image; the Next.js preset takes precedence over th
88
88
  - the `RAILWAY_SERVICE` variable: the service name;
89
89
  - the `APP_URL` variable: the public `https://` URL.
90
90
 
91
- Limit `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
91
+ Limit `dev`, `uat`, and `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
92
92
 
93
93
  3. Set the repository variable `DEPLOY_ENABLED` to `true`. Each push to `main` that passes CI then deploys to `dev`.
94
94
  4. Promote with **Actions → Deploy → Run workflow**, giving the environment and the full commit SHA. The workflow requires a successful CI run on `main` for that commit and a successful deployment to the previous environment, then waits for `/health`.
@@ -214,37 +214,46 @@ jobs:
214
214
  done
215
215
  } >> "$GITHUB_OUTPUT"
216
216
  - name: Lint Dockerfile
217
+ env:
218
+ AFFECTED_APP: ${{ steps.affected.outputs.app }}
219
+ AFFECTED_BACKOFFICE: ${{ steps.affected.outputs.backoffice }}
217
220
  run: |
218
221
  curl --silent --show-error --fail --location --output hadolint \
219
222
  "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-linux-x86_64"
220
223
  echo "${HADOLINT_SHA256} hadolint" | sha256sum --check --strict
221
224
  chmod +x hadolint
222
225
  files=()
223
- if [[ "${{ steps.affected.outputs.app }}" == "true" ]]; then
226
+ if [[ "$AFFECTED_APP" == "true" ]]; then
224
227
  files+=(apps/app/Dockerfile)
225
228
  fi
226
- if [[ "${{ steps.affected.outputs.backoffice }}" == "true" ]]; then
229
+ if [[ "$AFFECTED_BACKOFFICE" == "true" ]]; then
227
230
  files+=(apps/backoffice/Dockerfile)
228
231
  fi
229
232
  if [[ "${#files[@]}" -gt 0 ]]; then
230
233
  ./hadolint "${files[@]}"
231
234
  fi
232
235
  - name: Build images
236
+ env:
237
+ AFFECTED_APP: ${{ steps.affected.outputs.app }}
238
+ AFFECTED_BACKOFFICE: ${{ steps.affected.outputs.backoffice }}
233
239
  run: |
234
- if [[ "${{ steps.affected.outputs.app }}" == "true" ]]; then
240
+ if [[ "$AFFECTED_APP" == "true" ]]; then
235
241
  docker build --file apps/app/Dockerfile --tag app:ci .
236
242
  fi
237
- if [[ "${{ steps.affected.outputs.backoffice }}" == "true" ]]; then
243
+ if [[ "$AFFECTED_BACKOFFICE" == "true" ]]; then
238
244
  docker build --file apps/backoffice/Dockerfile --tag backoffice:ci .
239
245
  fi
240
246
  - name: Smoke test images
247
+ env:
248
+ AFFECTED_APP: ${{ steps.affected.outputs.app }}
249
+ AFFECTED_BACKOFFICE: ${{ steps.affected.outputs.backoffice }}
241
250
  id: smoke
242
251
  run: |
243
- if [[ "${{ steps.affected.outputs.app }}" == "true" ]]; then
252
+ if [[ "$AFFECTED_APP" == "true" ]]; then
244
253
  docker run --detach --name app --env PORT=3000 --publish 3000:3000 app:ci
245
254
  curl --silent --show-error --fail --retry 15 --retry-delay 1 --retry-all-errors --output /dev/null http://localhost:3000/health
246
255
  fi
247
- if [[ "${{ steps.affected.outputs.backoffice }}" == "true" ]]; then
256
+ if [[ "$AFFECTED_BACKOFFICE" == "true" ]]; then
248
257
  docker run --detach --name backoffice --env PORT=3001 --env DATABASE_URL=postgres://build-only@localhost/build-only --env PAYLOAD_SECRET=ci-only-secret --env APP_URL=http://localhost:3001 --publish 3001:3001 backoffice:ci
249
258
  curl --silent --show-error --fail --retry 15 --retry-delay 1 --retry-all-errors --output /dev/null http://localhost:3001/health
250
259
  fi
@@ -258,16 +267,19 @@ jobs:
258
267
  docker logs backoffice
259
268
  fi
260
269
  - name: Scan images for vulnerabilities
270
+ env:
271
+ AFFECTED_APP: ${{ steps.affected.outputs.app }}
272
+ AFFECTED_BACKOFFICE: ${{ steps.affected.outputs.backoffice }}
261
273
  run: |
262
274
  archive="trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
263
275
  curl --silent --show-error --fail --location --output "$archive" \
264
276
  "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/${archive}"
265
277
  echo "${TRIVY_SHA256} ${archive}" | sha256sum --check --strict
266
278
  tar --extract --gzip --file "$archive" trivy
267
- if [[ "${{ steps.affected.outputs.app }}" == "true" ]]; then
279
+ if [[ "$AFFECTED_APP" == "true" ]]; then
268
280
  ./trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed --no-progress app:ci
269
281
  fi
270
- if [[ "${{ steps.affected.outputs.backoffice }}" == "true" ]]; then
282
+ if [[ "$AFFECTED_BACKOFFICE" == "true" ]]; then
271
283
  ./trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed --no-progress backoffice:ci
272
284
  fi
273
285
 
@@ -33,6 +33,7 @@ concurrency:
33
33
  jobs:
34
34
  verify:
35
35
  name: Verify the requested commit
36
+ if: github.ref == 'refs/heads/main'
36
37
  runs-on: ubuntu-latest
37
38
  timeout-minutes: 5
38
39
  permissions:
@@ -66,13 +67,14 @@ jobs:
66
67
  prod)
67
68
  previous=uat
68
69
  export EXPECTED_TITLE="Deploy $COMMIT_SHA to uat"
69
- deployed="$(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?event=workflow_dispatch&status=success&per_page=100" --jq '.workflow_runs[] | select(.display_title == env.EXPECTED_TITLE) | .id' | wc -l)"
70
+ deployed="$(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?event=workflow_dispatch&status=success&branch=main&per_page=100" --jq '.workflow_runs[] | select(.display_title == env.EXPECTED_TITLE) | .id' | wc -l)"
70
71
  ;;
71
72
  esac
72
73
  [[ "$deployed" -gt 0 ]] || { echo "::error::$COMMIT_SHA has no successful $previous deployment; promote through $previous first"; exit 1; }
73
74
 
74
75
  deploy:
75
76
  name: Deploy to ${{ inputs.environment }}
77
+ if: github.ref == 'refs/heads/main'
76
78
  needs: verify
77
79
  runs-on: ubuntu-latest
78
80
  timeout-minutes: 40
@@ -134,7 +136,7 @@ jobs:
134
136
  latest="$completed"
135
137
  previous="$candidate"
136
138
  fi
137
- done < <(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?status=success&per_page=50" --jq '.workflow_runs[] | [.id, .display_title] | @tsv')
139
+ done < <(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?status=success&branch=main&per_page=50" --jq '.workflow_runs[] | [.id, .display_title] | @tsv')
138
140
  while IFS=$'\t' read -r run_id head_sha; do
139
141
  [[ -z "$run_id" || "$head_sha" == "$COMMIT_SHA" ]] && continue
140
142
  completed="$(gh api "repos/$REPOSITORY/actions/runs/$run_id/jobs" | jq -r --arg env "$RAILWAY_ENVIRONMENT" '[.jobs[] | select(.conclusion == "success" and .name == "Deploy to \($env) / Deploy to \($env)") | .completed_at] | max // empty')"
@@ -34,8 +34,8 @@ Turborepo workspace in TypeScript on pnpm and Node.js `>=24.22.1 <25`. `apps/app
34
34
  ## Known pitfalls
35
35
 
36
36
  - **Next.js docs live per app**: this Next.js version differs from your training data. Read the guide in `apps/app/node_modules/next/dist/docs/` or `apps/backoffice/node_modules/next/dist/docs/` before writing Next.js code; the workspace root has no `next` package.
37
- - **Database for `pnpm dev` and end-to-end tests**: the backoffice needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`; the README lists every variable. Run `pnpm exec playwright install chromium` once before the first `pnpm test:e2e`.
38
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that names a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`, even when it only reads.
37
+ - **Database for `pnpm dev` and end-to-end tests**: the backoffice needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`; the README lists every variable. Run `pnpm --filter ./apps/app exec playwright install chromium` once before the first `pnpm test:e2e`.
38
+ - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
39
39
 
40
40
  ## Related documentation
41
41
 
@@ -94,7 +94,7 @@ On Vercel, deploy an app without its image. The Next.js preset takes precedence
94
94
  - the `APP_URL` variable: the public Next.js `https://` URL;
95
95
  - the `BACKOFFICE_URL` variable: the public backoffice `https://` URL.
96
96
 
97
- Limit `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
97
+ Limit `dev`, `uat`, and `prod` to the `main` branch and add required reviewers. Environment secrets and variables in a private repository need GitHub Pro, Team, or Enterprise; required reviewers in a private repository need GitHub Enterprise.
98
98
 
99
99
  3. Set the repository variable `DEPLOY_ENABLED` to `true`. Each push to `main` that passes CI then deploys to `dev`. The workflow compares the commit with the last GitHub deployment to that environment and runs `railway up` only for services whose packages changed. A promotion through `uat` or `prod` uses the same comparison against the commit last deployed there, so several commits still ship every changed service. The first deploy to an environment ships both services.
100
100
  4. Promote with **Actions → Deploy → Run workflow**, giving the environment and the full commit SHA. The workflow requires a successful CI run on `main` for that commit and a successful deployment to the previous environment, then waits for `/health` on each service it uploaded.