@next-friday/create-app 0.0.0-stage → 1.0.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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -2
  3. package/dist/main.mjs +414 -0
  4. package/package.json +84 -3
  5. package/templates/base/.agents/hooks/agent-shell-gate.sh +355 -0
  6. package/templates/base/.agents/hooks/agent-suppression-gate.sh +45 -0
  7. package/templates/base/.agents/rules/automation-owned-checks.md +5 -0
  8. package/templates/base/.agents/rules/code-comments.md +3 -0
  9. package/templates/base/.agents/rules/current-state-authority.md +17 -0
  10. package/templates/base/.agents/rules/demand-driven-configuration.md +7 -0
  11. package/templates/base/.agents/rules/dependency-security.md +5 -0
  12. package/templates/base/.agents/rules/deterministic-testing.md +15 -0
  13. package/templates/base/.agents/rules/diagnostics-and-error-handling.md +7 -0
  14. package/templates/base/.agents/rules/git-workflow.md +10 -0
  15. package/templates/base/.agents/rules/no-suppression.md +7 -0
  16. package/templates/base/.agents/rules/script-driven-changes.md +7 -0
  17. package/templates/base/.agents/rules/single-author-style.md +7 -0
  18. package/templates/base/.claude/rules/agents-guide.md +1 -0
  19. package/templates/base/.claude/rules/automation-owned-checks.md +1 -0
  20. package/templates/base/.claude/rules/code-comments.md +1 -0
  21. package/templates/base/.claude/rules/current-state-authority.md +1 -0
  22. package/templates/base/.claude/rules/demand-driven-configuration.md +1 -0
  23. package/templates/base/.claude/rules/dependency-security.md +12 -0
  24. package/templates/base/.claude/rules/diagnostics-and-error-handling.md +1 -0
  25. package/templates/base/.claude/rules/git-workflow.md +1 -0
  26. package/templates/base/.claude/rules/no-suppression.md +1 -0
  27. package/templates/base/.claude/rules/script-driven-changes.md +1 -0
  28. package/templates/base/.claude/rules/single-author-style.md +1 -0
  29. package/templates/base/.claude/settings.json +61 -0
  30. package/templates/base/.commitlintrc.json +3 -0
  31. package/templates/base/.cursor/BUGBOT.md +17 -0
  32. package/templates/base/.cursor/hooks/agent-constitution-gate.sh +32 -0
  33. package/templates/base/.cursor/hooks.json +26 -0
  34. package/templates/base/.cursor/rules/automation-owned-checks.mdc +10 -0
  35. package/templates/base/.cursor/rules/code-comments.mdc +8 -0
  36. package/templates/base/.cursor/rules/current-state-authority.mdc +22 -0
  37. package/templates/base/.cursor/rules/demand-driven-configuration.mdc +12 -0
  38. package/templates/base/.cursor/rules/dependency-security.mdc +11 -0
  39. package/templates/base/.cursor/rules/diagnostics-and-error-handling.mdc +12 -0
  40. package/templates/base/.cursor/rules/git-workflow.mdc +15 -0
  41. package/templates/base/.cursor/rules/no-suppression.mdc +12 -0
  42. package/templates/base/.cursor/rules/script-driven-changes.mdc +12 -0
  43. package/templates/base/.cursor/rules/single-author-style.mdc +12 -0
  44. package/templates/base/.editorconfig +13 -0
  45. package/templates/base/.gitattributes +1 -0
  46. package/templates/base/.github/CODEOWNERS +2 -0
  47. package/templates/base/.github/ISSUE_TEMPLATE/config.yml +1 -0
  48. package/templates/base/.github/dependabot.yml +77 -0
  49. package/templates/base/.github/file-filters.yml +19 -0
  50. package/templates/base/.github/labeler.yml +25 -0
  51. package/templates/base/.github/requirements/diff-cover.txt +213 -0
  52. package/templates/base/.github/workflows/deploy.yml +124 -0
  53. package/templates/base/.github/workflows/osv-scanner.yml +34 -0
  54. package/templates/base/.github/workflows/pr-triage.yml +29 -0
  55. package/templates/base/.github/workflows/secret-scan.yml +50 -0
  56. package/templates/base/.github/workflows/validate-pr-title.yml +48 -0
  57. package/templates/base/.github/workflows/zizmor.yml +62 -0
  58. package/templates/base/.github/zizmor.yml +4 -0
  59. package/templates/base/.gitleaks.toml +14 -0
  60. package/templates/base/.husky/commit-msg +3 -0
  61. package/templates/base/.husky/pre-commit +17 -0
  62. package/templates/base/.husky/pre-merge-commit +7 -0
  63. package/templates/base/.husky/pre-push +15 -0
  64. package/templates/base/.nvmrc +1 -0
  65. package/templates/base/SECURITY.md +15 -0
  66. package/templates/base/knip.json +3 -0
  67. package/templates/base/pnpm-workspace.yaml +18 -0
  68. package/templates/base/railway.json +9 -0
  69. package/templates/base/scripts/check-agent-gates.ts +252 -0
  70. package/templates/base/scripts/sync-agent-rules.ts +121 -0
  71. package/templates/nestjs/.agents/rules/typescript-first.md +7 -0
  72. package/templates/nestjs/.agents/rules.json +41 -0
  73. package/templates/nestjs/.claude/rules/deterministic-testing.md +20 -0
  74. package/templates/nestjs/.claude/rules/typescript-first.md +13 -0
  75. package/templates/nestjs/.cursor/rules/deterministic-testing.mdc +21 -0
  76. package/templates/nestjs/.cursor/rules/typescript-first.mdc +13 -0
  77. package/templates/nestjs/.dependency-cruiser.json +28 -0
  78. package/templates/nestjs/.dockerignore +8 -0
  79. package/templates/nestjs/.env.example +1 -0
  80. package/templates/nestjs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  81. package/templates/nestjs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  82. package/templates/nestjs/.github/pull_request_template.md +25 -0
  83. package/templates/nestjs/.github/workflows/ci.yml +181 -0
  84. package/templates/nestjs/.github/workflows/sast.yml +45 -0
  85. package/templates/nestjs/.lintstagedrc.json +10 -0
  86. package/templates/nestjs/.prettierignore +2 -0
  87. package/templates/nestjs/.prettierrc.json +1 -0
  88. package/templates/nestjs/AGENTS.md +8 -0
  89. package/templates/nestjs/CONTRIBUTING.md +57 -0
  90. package/templates/nestjs/Dockerfile +27 -0
  91. package/templates/nestjs/README.md +78 -0
  92. package/templates/nestjs/_gitignore +47 -0
  93. package/templates/nestjs/eslint.config.ts +7 -0
  94. package/templates/nestjs/package.json +83 -0
  95. package/templates/nestjs/src/app.controller.test.ts +23 -0
  96. package/templates/nestjs/src/app.controller.ts +13 -0
  97. package/templates/nestjs/src/app.module.ts +12 -0
  98. package/templates/nestjs/src/app.service.ts +10 -0
  99. package/templates/nestjs/src/health/health.controller.test.ts +17 -0
  100. package/templates/nestjs/src/health/health.controller.ts +14 -0
  101. package/templates/nestjs/src/health/health.module.ts +10 -0
  102. package/templates/nestjs/src/main.ts +25 -0
  103. package/templates/nestjs/src/port.test.ts +29 -0
  104. package/templates/nestjs/src/port.ts +20 -0
  105. package/templates/nestjs/test/app.e2e.test.ts +40 -0
  106. package/templates/nestjs/tsconfig.build.json +9 -0
  107. package/templates/nestjs/tsconfig.json +20 -0
  108. package/templates/nestjs/vitest.config.ts +13 -0
  109. package/templates/nestjs/vitest.e2e.config.ts +8 -0
  110. package/templates/nextjs/.agents/rules/typescript-first.md +7 -0
  111. package/templates/nextjs/.agents/rules.json +41 -0
  112. package/templates/nextjs/.claude/rules/deterministic-testing.md +21 -0
  113. package/templates/nextjs/.claude/rules/typescript-first.md +15 -0
  114. package/templates/nextjs/.cursor/rules/deterministic-testing.mdc +21 -0
  115. package/templates/nextjs/.cursor/rules/typescript-first.mdc +13 -0
  116. package/templates/nextjs/.dependency-cruiser.json +34 -0
  117. package/templates/nextjs/.dockerignore +10 -0
  118. package/templates/nextjs/.env.example +1 -0
  119. package/templates/nextjs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  120. package/templates/nextjs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  121. package/templates/nextjs/.github/pull_request_template.md +25 -0
  122. package/templates/nextjs/.github/workflows/ci.yml +187 -0
  123. package/templates/nextjs/.github/workflows/sast.yml +46 -0
  124. package/templates/nextjs/.lintstagedrc.json +10 -0
  125. package/templates/nextjs/.prettierignore +2 -0
  126. package/templates/nextjs/AGENTS.md +18 -0
  127. package/templates/nextjs/CONTRIBUTING.md +57 -0
  128. package/templates/nextjs/Dockerfile +23 -0
  129. package/templates/nextjs/README.md +74 -0
  130. package/templates/nextjs/_gitignore +51 -0
  131. package/templates/nextjs/app/favicon.ico +0 -0
  132. package/templates/nextjs/app/globals.css +26 -0
  133. package/templates/nextjs/app/health/route.test.ts +20 -0
  134. package/templates/nextjs/app/health/route.ts +23 -0
  135. package/templates/nextjs/app/layout.tsx +29 -0
  136. package/templates/nextjs/app/page.test.ts +11 -0
  137. package/templates/nextjs/app/page.tsx +8 -0
  138. package/templates/nextjs/eslint.config.ts +32 -0
  139. package/templates/nextjs/knip.json +4 -0
  140. package/templates/nextjs/next.config.ts +35 -0
  141. package/templates/nextjs/package.json +78 -0
  142. package/templates/nextjs/playwright.config.ts +27 -0
  143. package/templates/nextjs/postcss.config.mjs +7 -0
  144. package/templates/nextjs/prettier.config.ts +11 -0
  145. package/templates/nextjs/test/home.e2e.test.ts +11 -0
  146. package/templates/nextjs/tsconfig.json +33 -0
  147. package/templates/nextjs/vitest.config.ts +12 -0
  148. package/templates/nodejs/.agents/rules/typescript-first.md +7 -0
  149. package/templates/nodejs/.agents/rules.json +41 -0
  150. package/templates/nodejs/.claude/rules/deterministic-testing.md +20 -0
  151. package/templates/nodejs/.claude/rules/typescript-first.md +13 -0
  152. package/templates/nodejs/.cursor/rules/deterministic-testing.mdc +21 -0
  153. package/templates/nodejs/.cursor/rules/typescript-first.mdc +13 -0
  154. package/templates/nodejs/.dependency-cruiser.json +28 -0
  155. package/templates/nodejs/.dockerignore +8 -0
  156. package/templates/nodejs/.env.example +1 -0
  157. package/templates/nodejs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  158. package/templates/nodejs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  159. package/templates/nodejs/.github/pull_request_template.md +25 -0
  160. package/templates/nodejs/.github/workflows/ci.yml +179 -0
  161. package/templates/nodejs/.github/workflows/sast.yml +45 -0
  162. package/templates/nodejs/.lintstagedrc.json +10 -0
  163. package/templates/nodejs/.prettierignore +2 -0
  164. package/templates/nodejs/.prettierrc.json +1 -0
  165. package/templates/nodejs/AGENTS.md +8 -0
  166. package/templates/nodejs/CONTRIBUTING.md +56 -0
  167. package/templates/nodejs/Dockerfile +27 -0
  168. package/templates/nodejs/README.md +74 -0
  169. package/templates/nodejs/_gitignore +47 -0
  170. package/templates/nodejs/eslint.config.ts +7 -0
  171. package/templates/nodejs/package.json +66 -0
  172. package/templates/nodejs/src/main.ts +22 -0
  173. package/templates/nodejs/src/port.test.ts +30 -0
  174. package/templates/nodejs/src/port.ts +20 -0
  175. package/templates/nodejs/src/server.test.ts +60 -0
  176. package/templates/nodejs/src/server.ts +37 -0
  177. package/templates/nodejs/tsconfig.build.json +9 -0
  178. package/templates/nodejs/tsconfig.json +19 -0
  179. package/templates/nodejs/vitest.config.ts +12 -0
  180. package/templates/payload/.agents/rules/typescript-first.md +7 -0
  181. package/templates/payload/.agents/rules.json +41 -0
  182. package/templates/payload/.claude/rules/deterministic-testing.md +21 -0
  183. package/templates/payload/.claude/rules/typescript-first.md +15 -0
  184. package/templates/payload/.cursor/rules/deterministic-testing.mdc +21 -0
  185. package/templates/payload/.cursor/rules/typescript-first.mdc +13 -0
  186. package/templates/payload/.dependency-cruiser.json +34 -0
  187. package/templates/payload/.dockerignore +9 -0
  188. package/templates/payload/.editorconfig-checker.json +3 -0
  189. package/templates/payload/.env.example +4 -0
  190. package/templates/payload/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  191. package/templates/payload/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  192. package/templates/payload/.github/pull_request_template.md +25 -0
  193. package/templates/payload/.github/workflows/ci.yml +204 -0
  194. package/templates/payload/.github/workflows/sast.yml +46 -0
  195. package/templates/payload/.lintstagedrc.json +10 -0
  196. package/templates/payload/.prettierignore +5 -0
  197. package/templates/payload/.prettierrc.json +1 -0
  198. package/templates/payload/AGENTS.md +19 -0
  199. package/templates/payload/CONTRIBUTING.md +58 -0
  200. package/templates/payload/Dockerfile +26 -0
  201. package/templates/payload/README.md +98 -0
  202. package/templates/payload/_gitignore +52 -0
  203. package/templates/payload/eslint.config.ts +35 -0
  204. package/templates/payload/next.config.ts +43 -0
  205. package/templates/payload/package.json +86 -0
  206. package/templates/payload/playwright.config.ts +27 -0
  207. package/templates/payload/src/app/(frontend)/layout.tsx +18 -0
  208. package/templates/payload/src/app/(frontend)/page.test.ts +14 -0
  209. package/templates/payload/src/app/(frontend)/page.tsx +14 -0
  210. package/templates/payload/src/app/(frontend)/styles.css +15 -0
  211. package/templates/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx +24 -0
  212. package/templates/payload/src/app/(payload)/admin/[[...segments]]/page.tsx +24 -0
  213. package/templates/payload/src/app/(payload)/admin/importMap.ts +6 -0
  214. package/templates/payload/src/app/(payload)/api/[...slug]/route.ts +19 -0
  215. package/templates/payload/src/app/(payload)/api/graphql/route.ts +8 -0
  216. package/templates/payload/src/app/(payload)/api/graphql-playground/route.ts +7 -0
  217. package/templates/payload/src/app/(payload)/custom.scss +0 -0
  218. package/templates/payload/src/app/(payload)/layout.tsx +31 -0
  219. package/templates/payload/src/app/health/route.test.ts +20 -0
  220. package/templates/payload/src/app/health/route.ts +23 -0
  221. package/templates/payload/src/collections/media.test.ts +27 -0
  222. package/templates/payload/src/collections/media.ts +18 -0
  223. package/templates/payload/src/collections/users.test.ts +10 -0
  224. package/templates/payload/src/collections/users.ts +10 -0
  225. package/templates/payload/src/environment.test.ts +32 -0
  226. package/templates/payload/src/environment.ts +14 -0
  227. package/templates/payload/src/migrations/20261030_005055_initial.json +969 -0
  228. package/templates/payload/src/migrations/20261030_005055_initial.ts +134 -0
  229. package/templates/payload/src/migrations/index.ts +9 -0
  230. package/templates/payload/src/payload-types.ts +339 -0
  231. package/templates/payload/src/payload.config.ts +47 -0
  232. package/templates/payload/test/home.e2e.test.ts +16 -0
  233. package/templates/payload/tsconfig.json +34 -0
  234. package/templates/payload/vitest.config.ts +19 -0
@@ -0,0 +1,37 @@
1
+ import {createServer} from "node:http";
2
+ import type {Server} from "node:http";
3
+
4
+ /**
5
+ * Create the HTTP server. `GET` or `HEAD` `/health` reports that the process is up; every other request gets 404.
6
+ * @returns A server that is not listening yet.
7
+ */
8
+ export function createAppServer(): Server {
9
+ return createServer((request, response) => {
10
+ const {pathname} = new URL(request.url ?? "/", "http://localhost");
11
+
12
+ if (pathname === "/health" && (request.method === "GET" || request.method === "HEAD")) {
13
+ response.writeHead(200, {
14
+ "Cache-Control": "no-store",
15
+ "Content-Type": "application/json",
16
+ });
17
+
18
+ response.end(
19
+ JSON.stringify({
20
+ status: "ok",
21
+ }),
22
+ );
23
+
24
+ return;
25
+ }
26
+
27
+ response.writeHead(404, {
28
+ "Content-Type": "application/json",
29
+ });
30
+
31
+ response.end(
32
+ JSON.stringify({
33
+ status: "not found",
34
+ }),
35
+ );
36
+ });
37
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "types": ["node"]
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["node_modules", "test", "dist", "**/*.test.ts"]
9
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "module": "nodenext",
5
+ "isolatedModules": true,
6
+ "removeComments": true,
7
+ "incremental": true,
8
+ "resolveJsonModule": true,
9
+ "skipLibCheck": true,
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "rootDir": ".",
13
+ "types": ["node"],
14
+ "strict": true,
15
+ "rewriteRelativeImportExtensions": true
16
+ },
17
+ "include": ["**/*.ts"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -0,0 +1,12 @@
1
+ import {defineConfig} from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ coverage: {
6
+ reporter: ["text", "html", "cobertura"],
7
+ include: ["src/**/*.ts"],
8
+ exclude: ["src/**/*.test.ts", "src/main.ts"],
9
+ },
10
+ include: ["src/**/*.test.ts"],
11
+ },
12
+ });
@@ -0,0 +1,7 @@
1
+ # TypeScript-First
2
+
3
+ In a TypeScript-capable app or package, write source, tests, and scripts as `.ts`, and JSX as `.tsx`. Use that extension for new work and for any JavaScript file whose implementation this change already touches, then update its imports, scripts, tests, and configuration in the same change.
4
+
5
+ Keep other languages in separately maintained components. Use a non-TypeScript extension when the runtime, tool, or public contract requires it.
6
+
7
+ _Completion criterion_: Every file this change created or materially rewrote in a TypeScript-capable project uses the TypeScript extension the runtime accepts, and its imports and scripts resolve.
@@ -0,0 +1,41 @@
1
+ {
2
+ "automation-owned-checks": {
3
+ "description": "Owned checks: hooks and CI define what must pass; run checks by hand to verify"
4
+ },
5
+ "code-comments": {
6
+ "description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
7
+ },
8
+ "current-state-authority": {
9
+ "description": "Current state: implement from user requirements and the working tree"
10
+ },
11
+ "demand-driven-configuration": {
12
+ "description": "Demand-driven configuration: add a setting only for an active requirement"
13
+ },
14
+ "dependency-security": {
15
+ "description": "Dependencies: add a package only when code or a contract uses it",
16
+ "globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
17
+ },
18
+ "deterministic-testing": {
19
+ "description": "Test admission: add a case only when it catches a defect current tests miss",
20
+ "globs": ["**/*.test.ts", "**/*.test.tsx"]
21
+ },
22
+ "diagnostics-and-error-handling": {
23
+ "description": "Diagnostics: fix runtime failures at the source and keep the root cause"
24
+ },
25
+ "git-workflow": {
26
+ "description": "Git workflow: trunk-based branches, commits, and pull requests"
27
+ },
28
+ "no-suppression": {
29
+ "description": "Findings: fix scanner and linter reports without inline suppressions"
30
+ },
31
+ "script-driven-changes": {
32
+ "description": "Scripts: apply a repeated edit across many files with a script"
33
+ },
34
+ "single-author-style": {
35
+ "description": "Sibling style: match layout, naming, and composition in the same project"
36
+ },
37
+ "typescript-first": {
38
+ "description": "TypeScript-first: write source, tests, and scripts as .ts or .tsx",
39
+ "globs": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"]
40
+ }
41
+ }
@@ -0,0 +1,21 @@
1
+ ---
2
+ paths:
3
+ - "**/*.test.ts"
4
+ - "**/*.test.tsx"
5
+ ---
6
+
7
+ # Test Admission
8
+
9
+ Keep tests as small, deterministic protections for observable contracts.
10
+
11
+ Name the contract and the distinct defect a proposed test can detect before writing it. Admit a test for externally observable behavior, a public contract, a demonstrated regression, a non-trivial invariant, a meaningful failure mode, or an explicit repository verification requirement.
12
+
13
+ Choose the narrowest existing layer that owns that contract. Give each test one defect to detect. Add a case only when it catches a defect remaining cases miss. Treat coverage percentage as a measurement.
14
+
15
+ Search existing coverage first. Extend the file that already owns the contract. Create a file only when the contract has no owner or needs a different harness. Follow the nearest directory and naming pattern. Keep setup local until multiple tests share live runtime logic, then extract one helper.
16
+
17
+ Use the framework's standard assertions. Use an inline snippet unless filesystem paths, module resolution, or compiler services are the contract. Keep fixtures declarative and read-only.
18
+
19
+ When the user asks to run tests, run the narrowest owning file or filter.
20
+
21
+ _Completion criterion_: Every added or modified case maps to an admitted contract and a defect current cases would miss. Tests stay unchanged when no proposed case survives admission.
@@ -0,0 +1,15 @@
1
+ ---
2
+ paths:
3
+ - "**/*.ts"
4
+ - "**/*.tsx"
5
+ - "**/*.js"
6
+ - "**/*.jsx"
7
+ ---
8
+
9
+ # TypeScript-First
10
+
11
+ In a TypeScript-capable app or package, write source, tests, and scripts as `.ts`, and JSX as `.tsx`. Use that extension for new work and for any JavaScript file whose implementation this change already touches, then update its imports, scripts, tests, and configuration in the same change.
12
+
13
+ Keep other languages in separately maintained components. Use a non-TypeScript extension when the runtime, tool, or public contract requires it.
14
+
15
+ _Completion criterion_: Every file this change created or materially rewrote in a TypeScript-capable project uses the TypeScript extension the runtime accepts, and its imports and scripts resolve.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Test admission: add a case only when it catches a defect current tests miss"
3
+ globs: "**/*.test.ts,**/*.test.tsx"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Test Admission
8
+
9
+ Keep tests as small, deterministic protections for observable contracts.
10
+
11
+ Name the contract and the distinct defect a proposed test can detect before writing it. Admit a test for externally observable behavior, a public contract, a demonstrated regression, a non-trivial invariant, a meaningful failure mode, or an explicit repository verification requirement.
12
+
13
+ Choose the narrowest existing layer that owns that contract. Give each test one defect to detect. Add a case only when it catches a defect remaining cases miss. Treat coverage percentage as a measurement.
14
+
15
+ Search existing coverage first. Extend the file that already owns the contract. Create a file only when the contract has no owner or needs a different harness. Follow the nearest directory and naming pattern. Keep setup local until multiple tests share live runtime logic, then extract one helper.
16
+
17
+ Use the framework's standard assertions. Use an inline snippet unless filesystem paths, module resolution, or compiler services are the contract. Keep fixtures declarative and read-only.
18
+
19
+ When the user asks to run tests, run the narrowest owning file or filter.
20
+
21
+ _Completion criterion_: Every added or modified case maps to an admitted contract and a defect current cases would miss. Tests stay unchanged when no proposed case survives admission.
@@ -0,0 +1,13 @@
1
+ ---
2
+ description: "TypeScript-first: write source, tests, and scripts as .ts or .tsx"
3
+ globs: "**/*.ts,**/*.tsx,**/*.js,**/*.jsx"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # TypeScript-First
8
+
9
+ In a TypeScript-capable app or package, write source, tests, and scripts as `.ts`, and JSX as `.tsx`. Use that extension for new work and for any JavaScript file whose implementation this change already touches, then update its imports, scripts, tests, and configuration in the same change.
10
+
11
+ Keep other languages in separately maintained components. Use a non-TypeScript extension when the runtime, tool, or public contract requires it.
12
+
13
+ _Completion criterion_: Every file this change created or materially rewrote in a TypeScript-capable project uses the TypeScript extension the runtime accepts, and its imports and scripts resolve.
@@ -0,0 +1,34 @@
1
+ {
2
+ "extends": "dependency-cruiser/configs/recommended-strict",
3
+ "forbidden": [
4
+ {
5
+ "name": "no-orphans",
6
+ "to": {},
7
+ "from": {
8
+ "orphan": true,
9
+ "pathNot": [
10
+ "(^|/)tsconfig\\.json$",
11
+ "(^|/)eslint\\.config\\.ts$",
12
+ "(^|/)next\\.config\\.ts$",
13
+ "(^|/)vitest[.]config[.]ts$",
14
+ "(^|/)playwright[.]config[.]ts$",
15
+ "^test/.*[.]e2e[.]test[.]ts$",
16
+ "^src/app/.*(page|layout|template|loading|error|not-found|default|route)[.]tsx?$",
17
+ "^src/payload-types[.]ts$"
18
+ ]
19
+ }
20
+ }
21
+ ],
22
+ "options": {
23
+ "skipAnalysisNotInRules": true,
24
+ "tsPreCompilationDeps": true,
25
+ "enhancedResolveOptions": {
26
+ "conditionNames": ["import", "require", "node", "default", "types"],
27
+ "exportsFields": ["exports"]
28
+ },
29
+ "exclude": "(^|/)(?:\\.next|coverage|node_modules)/|^src/app/[(]payload[)]/",
30
+ "tsConfig": {
31
+ "fileName": "tsconfig.json"
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,9 @@
1
+ *
2
+ !package.json
3
+ !pnpm-lock.yaml
4
+ !pnpm-workspace.yaml
5
+ !next.config.ts
6
+ !tsconfig.json
7
+ !src/
8
+ src/**/*.test.ts
9
+ src/**/*.test.tsx
@@ -0,0 +1,3 @@
1
+ {
2
+ "Exclude": ["^src/migrations/", "^src/payload-types\\.ts$"]
3
+ }
@@ -0,0 +1,4 @@
1
+ # Copy to .env and fill in. List every environment variable the app reads, with a safe example value.
2
+ DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/payload
3
+ PAYLOAD_SECRET=
4
+ APP_URL=http://localhost:3000
@@ -0,0 +1,66 @@
1
+ name: Bug report
2
+ description: Report crashes, incorrect behavior, or setup problems.
3
+ labels: ["bug", "needs triage"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Reproduce the issue with the supported Node.js version.
9
+ Remove credentials, secrets, personal or customer data, and proprietary source code before submitting.
10
+ - type: checkboxes
11
+ id: preflight
12
+ attributes:
13
+ label: Before you submit
14
+ description: Confirm these items before submitting the report.
15
+ options:
16
+ - label: I searched existing issues and didn't find a matching report.
17
+ required: true
18
+ - label: I can reproduce this issue on the latest commit of the default branch.
19
+ required: true
20
+ - type: input
21
+ id: version
22
+ attributes:
23
+ label: Commit
24
+ placeholder: 769e0ef
25
+ validations:
26
+ required: true
27
+ - type: textarea
28
+ id: environment
29
+ attributes:
30
+ label: Environment
31
+ description: List Node.js, operating system, package manager, browser, and device.
32
+ placeholder: |
33
+ Node.js: 24.22.1
34
+ OS: Ubuntu 24.04 / macOS
35
+ Package manager: pnpm 12.6.0
36
+ Browser: Chrome on Android
37
+ validations:
38
+ required: true
39
+ - type: textarea
40
+ id: reproduction
41
+ attributes:
42
+ label: Minimal reproduction
43
+ description: Link to a minimal public reproduction or provide sanitized code and configuration that reproduce the issue.
44
+ validations:
45
+ required: true
46
+ - type: textarea
47
+ id: expected
48
+ attributes:
49
+ label: Expected behavior
50
+ description: Describe the behavior you expected.
51
+ validations:
52
+ required: true
53
+ - type: textarea
54
+ id: actual
55
+ attributes:
56
+ label: Actual behavior
57
+ description: Describe what happened, including errors and logs.
58
+ validations:
59
+ required: true
60
+ - type: checkboxes
61
+ id: safety
62
+ attributes:
63
+ label: Sensitive information
64
+ options:
65
+ - label: I removed credentials, secrets, personal or customer data, and proprietary code from this report.
66
+ required: true
@@ -0,0 +1,50 @@
1
+ name: Feature request
2
+ description: Suggest a specific change to next-friday-template-payload.
3
+ labels: ["enhancement", "needs triage"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Use this form for changes that are ready to evaluate.
9
+ - type: dropdown
10
+ id: scope
11
+ attributes:
12
+ label: Affected area
13
+ description: Select the area this request affects.
14
+ options:
15
+ - Pages and routes
16
+ - Collections and admin panel
17
+ - Configuration and environment
18
+ - Tooling / CI
19
+ - Documentation
20
+ - Repository governance
21
+ validations:
22
+ required: true
23
+ - type: textarea
24
+ id: problem
25
+ attributes:
26
+ label: Problem
27
+ description: Describe the problem or use case.
28
+ validations:
29
+ required: true
30
+ - type: textarea
31
+ id: proposal
32
+ attributes:
33
+ label: Proposed change
34
+ description: Describe the smallest change that solves the problem.
35
+ validations:
36
+ required: true
37
+ - type: textarea
38
+ id: alternatives
39
+ attributes:
40
+ label: Alternatives considered
41
+ description: List existing options you considered.
42
+ validations:
43
+ required: false
44
+ - type: checkboxes
45
+ id: breaking
46
+ attributes:
47
+ label: Breaking change
48
+ description: Indicate whether this request changes behavior for existing users.
49
+ options:
50
+ - label: This request changes an existing page route, collection, API, or public contract.
@@ -0,0 +1,25 @@
1
+ <!-- Title: `<type>(<scope>): <subject>` with a lowercase scope and a subject of 50 characters or fewer. Repository workflows validate it. The squash merge puts the title on `main`. Delete a section that has nothing to say, except Scope. -->
2
+
3
+ ## Why
4
+
5
+ <!-- The problem and the approach in 1-3 short sentences. No SHAs or rebase history. Link a related issue with `Closes #123`. -->
6
+
7
+ ## What changed
8
+
9
+ <!-- 1-3 short bullets. Name a symbol or path only when it carries the change, and both sides of a rename. Name every added, changed, or removed page, collection or field, migration, and environment variable. Document new variables in `.env.example`. -->
10
+
11
+ ## Scope
12
+
13
+ <!-- 1-3 short items: what this covers and what it deliberately leaves out. -->
14
+
15
+ ## Tradeoffs
16
+
17
+ <!-- Only rejected alternatives a reviewer would ask about. -->
18
+
19
+ ## Blast Radius
20
+
21
+ <!-- 1-2 sentences on who or what this touches and why that is safe or risky. If main is red, state the cost of leaving it red. -->
22
+
23
+ ## Verification
24
+
25
+ <!-- 1-3 bullets, each a check you ran and its outcome. For a perf change, one number as before -> after. After this section, attach videos or screenshots that prove a claim. -->
@@ -0,0 +1,204 @@
1
+ name: Verify
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
6
+ push:
7
+ branches:
8
+ - main
9
+ schedule:
10
+ - cron: "0 3 * * 1"
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ changes:
21
+ name: Detect Changes
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 5
24
+ permissions:
25
+ contents: read
26
+ pull-requests: read # Needed by paths-filter to inspect pull request changes.
27
+ outputs:
28
+ heavy: ${{ steps.filter.outputs.heavy }}
29
+ ci_policy: ${{ steps.filter.outputs.ci_policy }}
30
+ full_verification: ${{ steps.mode.outputs.full_verification }}
31
+ steps:
32
+ - name: Checkout repository
33
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
34
+ with:
35
+ persist-credentials: false
36
+ - name: Detect relevant changes
37
+ id: filter
38
+ if: github.event_name == 'pull_request'
39
+ uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
40
+ with:
41
+ predicate-quantifier: some-with-excludes
42
+ filters: .github/file-filters.yml
43
+ - name: Select verification mode
44
+ id: mode
45
+ shell: bash
46
+ env:
47
+ EVENT_NAME: ${{ github.event_name }}
48
+ DRAFT: ${{ github.event.pull_request.draft }}
49
+ HEAVY: ${{ steps.filter.outputs.heavy }}
50
+ CI_POLICY: ${{ steps.filter.outputs.ci_policy }}
51
+ run: |
52
+ full_verification=false
53
+ if [[ "$EVENT_NAME" == "push" || ( "$EVENT_NAME" == "pull_request" && "$DRAFT" != "true" && ( "$HEAVY" == "true" || "$CI_POLICY" == "true" ) ) ]]; then
54
+ full_verification=true
55
+ fi
56
+
57
+ echo "full_verification=$full_verification" >> "$GITHUB_OUTPUT"
58
+
59
+ checks:
60
+ name: Static Checks, Tests & Build
61
+ needs: changes
62
+ if: needs.changes.outputs.full_verification == 'true'
63
+ runs-on: ubuntu-latest
64
+ timeout-minutes: 20
65
+ services:
66
+ postgres:
67
+ image: postgres:17.11-alpine@sha256:266d3c257594e195b309ae9d1805e54c788f1d7b375f56bf6c367aac6c917e7b
68
+ env:
69
+ POSTGRES_PASSWORD: postgres
70
+ POSTGRES_DB: payload
71
+ ports:
72
+ - 5432:5432
73
+ options: >-
74
+ --health-cmd "pg_isready --username postgres"
75
+ --health-interval 5s
76
+ --health-timeout 5s
77
+ --health-retries 10
78
+ env:
79
+ DATABASE_URL: postgres://postgres:postgres@localhost:5432/payload
80
+ PAYLOAD_SECRET: ci-only-secret
81
+ APP_URL: http://localhost:3000
82
+ steps:
83
+ - name: Checkout repository
84
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
85
+ with:
86
+ fetch-depth: 0
87
+ persist-credentials: false
88
+ - name: Set up Node.js and pnpm
89
+ uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0
90
+ with:
91
+ cache: true
92
+ require-lockfile: true
93
+ - name: Reject suppression directives
94
+ run: pnpm suppressions:check
95
+ - name: Check Cursor rules match .agents/rules
96
+ run: pnpm rules:check
97
+ - name: Check agent gates
98
+ run: pnpm gates:check
99
+ - name: Check lint
100
+ run: pnpm lint:check
101
+ - name: Check formatting
102
+ run: pnpm format:check
103
+ env:
104
+ GITHUB_TOKEN: ${{ github.token }} # editorconfig-checker downloads its binary from GitHub releases; the token avoids the anonymous rate limit.
105
+ - name: Check package.json ordering
106
+ run: pnpm sort-package-json:check
107
+ - name: Validate peer dependency contracts
108
+ run: pnpm peers:check
109
+ - name: Check types
110
+ run: pnpm typecheck
111
+ - name: Run Knip
112
+ run: pnpm knip
113
+ - name: Check dependency graph
114
+ run: pnpm depcruise
115
+ - name: Run tests with coverage
116
+ run: pnpm test:coverage
117
+ - name: Build
118
+ run: pnpm build
119
+ env:
120
+ NEXT_TELEMETRY_DISABLED: "1"
121
+ - name: Install Playwright browser
122
+ run: pnpm exec playwright install --with-deps chromium
123
+ - name: Run end-to-end tests
124
+ run: pnpm test:e2e
125
+ env:
126
+ NEXT_TELEMETRY_DISABLED: "1"
127
+ - name: Check patch coverage
128
+ if: github.event_name == 'pull_request'
129
+ env:
130
+ BASE_REF: ${{ github.base_ref }}
131
+ run: |
132
+ python3 -m venv "$RUNNER_TEMP/diff-cover"
133
+ "$RUNNER_TEMP/diff-cover/bin/pip" install --quiet --require-hashes --only-binary=:all: -r .github/requirements/diff-cover.txt
134
+ "$RUNNER_TEMP/diff-cover/bin/diff-cover" coverage/cobertura-coverage.xml --compare-branch "origin/$BASE_REF" --fail-under 95 --branch-coverage
135
+
136
+ image:
137
+ name: Container Image
138
+ needs: changes
139
+ if: needs.changes.outputs.full_verification == 'true' || github.event_name == 'schedule'
140
+ runs-on: ubuntu-latest
141
+ timeout-minutes: 15
142
+ env:
143
+ HADOLINT_VERSION: 2.15.1
144
+ HADOLINT_SHA256: c7187db94eeeeca956519a6af171adc31453941a1e777961f6e680f697c8c507
145
+ TRIVY_VERSION: 0.76.1
146
+ TRIVY_SHA256: c7cbe3137fb8a48a17574bede3dd6beb16742d1e9772929940fc90082c39d9c0
147
+ steps:
148
+ - name: Checkout repository
149
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
150
+ with:
151
+ persist-credentials: false
152
+ - name: Lint Dockerfile
153
+ run: |
154
+ curl --silent --show-error --fail --location --output hadolint \
155
+ "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-linux-x86_64"
156
+ echo "${HADOLINT_SHA256} hadolint" | sha256sum --check --strict
157
+ chmod +x hadolint
158
+ ./hadolint Dockerfile
159
+ - name: Build image
160
+ run: docker build --tag app:ci .
161
+ - name: Smoke test image
162
+ id: smoke
163
+ run: |
164
+ docker run --detach --name app --env PORT=3000 --publish 3000:3000 app:ci
165
+ curl --silent --show-error --fail --retry 15 --retry-delay 1 --retry-all-errors --output /dev/null http://localhost:3000/health
166
+ - name: Show container logs
167
+ if: failure() && steps.smoke.outcome == 'failure'
168
+ run: docker logs app
169
+ - name: Scan image for vulnerabilities
170
+ run: |
171
+ archive="trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
172
+ curl --silent --show-error --fail --location --output "$archive" \
173
+ "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/${archive}"
174
+ echo "${TRIVY_SHA256} ${archive}" | sha256sum --check --strict
175
+ tar --extract --gzip --file "$archive" trivy
176
+ ./trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed --no-progress app:ci
177
+
178
+ deploy-dev:
179
+ name: Deploy to dev
180
+ needs:
181
+ - checks
182
+ - image
183
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.DEPLOY_ENABLED == 'true'
184
+ permissions:
185
+ contents: read
186
+ actions: read # Needed by deploy.yml to find the CI run of the deployed commit.
187
+ uses: ./.github/workflows/deploy.yml
188
+ with:
189
+ environment: dev
190
+ commit_sha: ${{ github.sha }}
191
+
192
+ ci:
193
+ name: All Checks
194
+ if: always()
195
+ timeout-minutes: 5
196
+ needs:
197
+ - changes
198
+ - checks
199
+ - image
200
+ runs-on: ubuntu-latest
201
+ steps:
202
+ - name: Require all verification jobs
203
+ if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
204
+ run: exit 1
@@ -0,0 +1,46 @@
1
+ name: SAST
2
+
3
+ on:
4
+ pull_request: {}
5
+ push:
6
+ branches:
7
+ - main
8
+ paths-ignore:
9
+ - "**/*.md"
10
+ - ".agents/**"
11
+ - ".claude/**"
12
+ - ".cursor/**"
13
+ schedule:
14
+ - cron: "17 2 * * 1"
15
+
16
+ permissions: {}
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+ semgrep:
24
+ name: Semgrep (OWASP)
25
+ runs-on: ubuntu-latest
26
+ timeout-minutes: 15
27
+ permissions:
28
+ contents: read
29
+ container:
30
+ image: semgrep/semgrep:1.179.0@sha256:93963d9295a366f59e4850127b1550400ee7b388f04fe144e4a1f6325d96e01b
31
+ steps:
32
+ - name: Checkout repository
33
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
34
+ with:
35
+ persist-credentials: false
36
+ - name: Scan source
37
+ run: >-
38
+ semgrep scan
39
+ --config p/owasp-top-ten
40
+ --config p/typescript
41
+ --config p/nodejsscan
42
+ --config p/react
43
+ --severity ERROR --severity WARNING
44
+ --error --metrics=off
45
+ --timeout 60 --timeout-threshold 0
46
+ .
@@ -0,0 +1,10 @@
1
+ {
2
+ "*.{ts,tsx,js,jsx,mjs,cjs}": [
3
+ "pnpm exec eslint --fix --cache --max-warnings=0 --no-warn-ignored --no-inline-config",
4
+ "prettier --write --cache"
5
+ ],
6
+ "!(package).json": ["prettier --write --cache"],
7
+ "*.{css,scss,md,yml,yaml}": ["prettier --write --cache"],
8
+ "package.json": ["sort-package-json", "prettier --write --cache"],
9
+ ".husky/{commit-msg,pre-commit,pre-merge-commit,pre-push}": ["prettier --write --cache"]
10
+ }