@baldurpan/create-ai-workflow 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/agents-block.js +70 -0
- package/dist/bin.js +14 -0
- package/dist/check/markdown.js +47 -0
- package/dist/check/parse.js +113 -0
- package/dist/check/rules.js +245 -0
- package/dist/cli.js +109 -0
- package/dist/commands/check.js +41 -0
- package/dist/commands/install.js +76 -0
- package/dist/commands/standards-add.js +145 -0
- package/dist/commands/update.js +214 -0
- package/dist/layout.js +115 -0
- package/dist/log.js +20 -0
- package/dist/manifest.js +53 -0
- package/dist/paths.js +41 -0
- package/package.json +37 -0
- package/templates/blocks/agents-block.md +30 -0
- package/templates/claude/agents/planner.agent.md +60 -0
- package/templates/claude/agents/reviewer.agent.md +77 -0
- package/templates/context/README.md +81 -0
- package/templates/context/plan-template.md +69 -0
- package/templates/context/plan-template.notes.md +55 -0
- package/templates/context/roles/coder.md +76 -0
- package/templates/context/workflow.md +143 -0
- package/templates/skills/feature-close/SKILL.md +102 -0
- package/templates/skills/feature-implement/SKILL.md +142 -0
- package/templates/skills/feature-plan/SKILL.md +138 -0
- package/templates/skills/feature-status/SKILL.md +86 -0
- package/templates/skills/onboard/SKILL.md +122 -0
- package/templates/skills/orchestrate/SKILL.md +92 -0
- package/templates/skills/roadmap/SKILL.md +97 -0
- package/templates/standards/.source +8 -0
- package/templates/standards/README.md +104 -0
- package/templates/standards/architecture/api-design.md +212 -0
- package/templates/standards/architecture/dependency-boundaries.md +104 -0
- package/templates/standards/architecture/feature-driven.md +102 -0
- package/templates/standards/architecture/folder-structure.md +108 -0
- package/templates/standards/architecture/monorepos.md +107 -0
- package/templates/standards/architecture/refactoring.md +97 -0
- package/templates/standards/architecture/shared-code.md +81 -0
- package/templates/standards/docs/PHP-SPEC.md +1195 -0
- package/templates/standards/docs/SPEC.md +540 -0
- package/templates/standards/examples/bad/data-fetching.tsx +52 -0
- package/templates/standards/examples/bad/derived-state.tsx +60 -0
- package/templates/standards/examples/bad/feature-component.tsx +80 -0
- package/templates/standards/examples/bad/prop-drilling.tsx +70 -0
- package/templates/standards/examples/good/data-fetching.tsx +53 -0
- package/templates/standards/examples/good/derived-state.tsx +52 -0
- package/templates/standards/examples/good/feature-component.tsx +141 -0
- package/templates/standards/examples/good/invoice.schema.ts +20 -0
- package/templates/standards/examples/good/prop-drilling.tsx +83 -0
- package/templates/standards/philosophy/ai-agent-behavior.md +93 -0
- package/templates/standards/philosophy/core-principles.md +49 -0
- package/templates/standards/philosophy/incremental-abstraction.md +56 -0
- package/templates/standards/philosophy/maintainability.md +66 -0
- package/templates/standards/philosophy/readability.md +87 -0
- package/templates/standards/php/README.md +62 -0
- package/templates/standards/php/anti-patterns.md +259 -0
- package/templates/standards/php/architecture.md +241 -0
- package/templates/standards/php/frameworks.md +197 -0
- package/templates/standards/php/rules.md +205 -0
- package/templates/standards/php/security.md +190 -0
- package/templates/standards/php/testing.md +139 -0
- package/templates/standards/php/tooling.md +245 -0
- package/templates/standards/react/accessibility.md +130 -0
- package/templates/standards/react/anti-patterns.md +187 -0
- package/templates/standards/react/component-design.md +139 -0
- package/templates/standards/react/error-boundaries.md +195 -0
- package/templates/standards/react/forms.md +147 -0
- package/templates/standards/react/hooks.md +88 -0
- package/templates/standards/react/memoization.md +87 -0
- package/templates/standards/react/state-management.md +123 -0
- package/templates/standards/react/testing.md +118 -0
- package/templates/standards/react/use-effect.md +110 -0
- package/templates/standards/security/api-security.md +136 -0
- package/templates/standards/security/auth.md +112 -0
- package/templates/standards/security/secrets.md +105 -0
- package/templates/standards/security/validation.md +89 -0
- package/templates/standards/templates/.editorconfig +16 -0
- package/templates/standards/templates/.nvmrc +1 -0
- package/templates/standards/templates/AGENTS.md +46 -0
- package/templates/standards/templates/CLAUDE.md +3 -0
- package/templates/standards/templates/_dot_gitignore +50 -0
- package/templates/standards/templates/biome.json +53 -0
- package/templates/standards/templates/eslint.config.js +61 -0
- package/templates/standards/templates/project-readme.md +76 -0
- package/templates/standards/templates/pull-request-template.md +46 -0
- package/templates/standards/templates/tsconfig.json +35 -0
- package/templates/standards/tooling/biome.md +92 -0
- package/templates/standards/tooling/ci.md +128 -0
- package/templates/standards/tooling/dates.md +194 -0
- package/templates/standards/tooling/dependencies.md +90 -0
- package/templates/standards/tooling/nx.md +113 -0
- package/templates/standards/tooling/observability.md +183 -0
- package/templates/standards/tooling/prisma.md +152 -0
- package/templates/standards/tooling/shadcn.md +115 -0
- package/templates/standards/tooling/tailwind.md +135 -0
- package/templates/standards/tooling/tanstack-query.md +214 -0
- package/templates/standards/tooling/tanstack-router.md +365 -0
- package/templates/standards/tooling/tanstack.md +31 -0
- package/templates/standards/tooling/vite.md +135 -0
- package/templates/standards/typescript/anti-patterns.md +107 -0
- package/templates/standards/typescript/error-handling.md +216 -0
- package/templates/standards/typescript/naming.md +78 -0
- package/templates/standards/typescript/rules.md +159 -0
- package/templates/standards/typescript/tsconfig/base.json +32 -0
- package/templates/standards/typescript/tsconfig/nextjs.json +12 -0
- package/templates/standards/typescript/tsconfig/react.json +9 -0
- package/templates/standards/typescript/validation.md +104 -0
- package/templates/stubs/executors.md +49 -0
- package/templates/stubs/findings.md +40 -0
- package/templates/stubs/history.md +13 -0
- package/templates/stubs/roadmap.md +29 -0
- package/templates/stubs/stack.md +35 -0
- package/templates/stubs/verify.md +48 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Input Validation
|
|
2
|
+
|
|
3
|
+
## Core Rule
|
|
4
|
+
|
|
5
|
+
Validate all external input at system boundaries. Never trust data from users, external APIs, or environment variables.
|
|
6
|
+
|
|
7
|
+
## System Boundaries
|
|
8
|
+
|
|
9
|
+
External data that must always be validated:
|
|
10
|
+
|
|
11
|
+
- HTTP request bodies, query params, path params, headers
|
|
12
|
+
- Form submissions
|
|
13
|
+
- URL search params parsed client-side
|
|
14
|
+
- Environment variables
|
|
15
|
+
- File uploads
|
|
16
|
+
- Data from third-party APIs
|
|
17
|
+
- `localStorage` / `sessionStorage` values
|
|
18
|
+
- `postMessage` events
|
|
19
|
+
|
|
20
|
+
Internal data (function calls within the same service, TypeScript types) does not need runtime validation — trust the type system.
|
|
21
|
+
|
|
22
|
+
## Preferred Tool: Zod
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
// API route — validate request body
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
|
|
28
|
+
const createInvoiceBody = z.object({
|
|
29
|
+
title: z.string().min(1).max(200),
|
|
30
|
+
amount: z.number().positive(),
|
|
31
|
+
dueDate: z.coerce.date().min(new Date()),
|
|
32
|
+
recipientEmail: z.string().email(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
app.post("/api/invoices", async (req, res) => {
|
|
36
|
+
const result = createInvoiceBody.safeParse(req.body);
|
|
37
|
+
if (!result.success) {
|
|
38
|
+
return res.status(422).json({ errors: result.error.flatten() });
|
|
39
|
+
}
|
|
40
|
+
const invoice = await createInvoice(result.data);
|
|
41
|
+
return res.status(201).json(invoice);
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Path and Query Params
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const getInvoiceParams = z.object({
|
|
49
|
+
id: z.string().cuid(),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const getInvoicesQuery = z.object({
|
|
53
|
+
status: z.enum(["all", "open", "paid"]).default("all"),
|
|
54
|
+
page: z.coerce.number().int().positive().default(1),
|
|
55
|
+
limit: z.coerce.number().int().positive().max(100).default(20),
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## File Uploads
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const uploadSchema = z.object({
|
|
63
|
+
file: z
|
|
64
|
+
.instanceof(File)
|
|
65
|
+
.refine((f) => f.size <= 5 * 1024 * 1024, "Max file size is 5MB")
|
|
66
|
+
.refine(
|
|
67
|
+
(f) => ["image/jpeg", "image/png", "application/pdf"].includes(f.type),
|
|
68
|
+
"Only JPEG, PNG, and PDF files are allowed",
|
|
69
|
+
),
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## DO NOT
|
|
74
|
+
|
|
75
|
+
- Pass `req.body` directly to a database query or ORM
|
|
76
|
+
- Use `any` for data received from external sources
|
|
77
|
+
- Trust `Content-Type` headers alone to determine what data was sent
|
|
78
|
+
- Rely on client-side validation as the only validation
|
|
79
|
+
|
|
80
|
+
## PRIORITY
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Validate all external input > Trust internal TypeScript types
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## See Also
|
|
87
|
+
|
|
88
|
+
- [typescript/validation.md](../typescript/validation.md) — Zod patterns
|
|
89
|
+
- [api-security.md](api-security.md) — additional API-level protections
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
indent_style = space
|
|
7
|
+
indent_size = 2
|
|
8
|
+
insert_final_newline = true
|
|
9
|
+
trim_trailing_whitespace = true
|
|
10
|
+
max_line_length = 100
|
|
11
|
+
|
|
12
|
+
[*.md]
|
|
13
|
+
trim_trailing_whitespace = false
|
|
14
|
+
|
|
15
|
+
[Makefile]
|
|
16
|
+
indent_style = tab
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This project follows the [AI Engineering Standards](https://github.com/baldurpan/ai-engineering-standards).
|
|
4
|
+
|
|
5
|
+
Load that repo's [`README.md`](https://github.com/baldurpan/ai-engineering-standards/blob/main/README.md) and follow its conditional-loading guidance based on the task at hand.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Project
|
|
10
|
+
|
|
11
|
+
<!-- One sentence: what this project is and who it is for. -->
|
|
12
|
+
|
|
13
|
+
## Stack
|
|
14
|
+
|
|
15
|
+
<!-- Adjust to match this project. -->
|
|
16
|
+
|
|
17
|
+
- Language: TypeScript (strict)
|
|
18
|
+
- Framework: <!-- Next.js / Remix / Vite -->
|
|
19
|
+
- Styling: Tailwind CSS + shadcn/ui
|
|
20
|
+
- Data fetching: TanStack Query
|
|
21
|
+
- Forms: TanStack Form / React Hook Form + Zod
|
|
22
|
+
- Testing: Vitest + Testing Library + Playwright
|
|
23
|
+
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm dev # start dev server
|
|
28
|
+
pnpm build # production build
|
|
29
|
+
pnpm test # unit + integration tests
|
|
30
|
+
pnpm test:e2e # Playwright E2E tests
|
|
31
|
+
pnpm typecheck # TypeScript type check
|
|
32
|
+
pnpm lint # Biome lint
|
|
33
|
+
pnpm format # Biome format
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Key Directories
|
|
37
|
+
|
|
38
|
+
| Path | Purpose |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `src/features/` | Feature-driven modules — colocate components, hooks, schemas, tests |
|
|
41
|
+
| `src/shared/` | Reusable code used across 3+ features |
|
|
42
|
+
| `src/lib/` | Third-party adapters (db, auth, email) |
|
|
43
|
+
|
|
44
|
+
## Project-Specific Rules
|
|
45
|
+
|
|
46
|
+
<!-- Optional: any additions or overrides to the standards. Keep these focused on this project. -->
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules
|
|
3
|
+
.pnpm-store
|
|
4
|
+
.yarn
|
|
5
|
+
|
|
6
|
+
# Build output
|
|
7
|
+
dist
|
|
8
|
+
build
|
|
9
|
+
out
|
|
10
|
+
.next
|
|
11
|
+
.turbo
|
|
12
|
+
.nx/cache
|
|
13
|
+
.vercel
|
|
14
|
+
|
|
15
|
+
# TypeScript
|
|
16
|
+
*.tsbuildinfo
|
|
17
|
+
|
|
18
|
+
# Testing
|
|
19
|
+
coverage
|
|
20
|
+
.vitest
|
|
21
|
+
playwright-report
|
|
22
|
+
test-results
|
|
23
|
+
|
|
24
|
+
# Logs
|
|
25
|
+
*.log
|
|
26
|
+
npm-debug.log*
|
|
27
|
+
yarn-debug.log*
|
|
28
|
+
yarn-error.log*
|
|
29
|
+
pnpm-debug.log*
|
|
30
|
+
|
|
31
|
+
# Environment
|
|
32
|
+
.env
|
|
33
|
+
.env.local
|
|
34
|
+
.env.*.local
|
|
35
|
+
!.env.example
|
|
36
|
+
|
|
37
|
+
# Editor / OS
|
|
38
|
+
.DS_Store
|
|
39
|
+
.idea
|
|
40
|
+
.vscode/*
|
|
41
|
+
!.vscode/extensions.json
|
|
42
|
+
!.vscode/settings.json
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
Thumbs.db
|
|
46
|
+
|
|
47
|
+
# Secrets / credentials
|
|
48
|
+
*.pem
|
|
49
|
+
*.key
|
|
50
|
+
secrets.json
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
3
|
+
"organizeImports": {
|
|
4
|
+
"enabled": true
|
|
5
|
+
},
|
|
6
|
+
"formatter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"indentStyle": "space",
|
|
9
|
+
"indentWidth": 2,
|
|
10
|
+
"lineWidth": 100,
|
|
11
|
+
"lineEnding": "lf"
|
|
12
|
+
},
|
|
13
|
+
"javascript": {
|
|
14
|
+
"formatter": {
|
|
15
|
+
"quoteStyle": "double",
|
|
16
|
+
"trailingCommas": "all",
|
|
17
|
+
"semicolons": "always",
|
|
18
|
+
"arrowParentheses": "always"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"linter": {
|
|
22
|
+
"enabled": true,
|
|
23
|
+
"rules": {
|
|
24
|
+
"recommended": true,
|
|
25
|
+
"a11y": {
|
|
26
|
+
"recommended": true,
|
|
27
|
+
"noAriaHiddenOnFocusable": "error",
|
|
28
|
+
"noAutofocus": "warn",
|
|
29
|
+
"useAltText": "error",
|
|
30
|
+
"useButtonType": "error",
|
|
31
|
+
"useSemanticElements": "warn"
|
|
32
|
+
},
|
|
33
|
+
"correctness": {
|
|
34
|
+
"noUnusedImports": "error",
|
|
35
|
+
"noUnusedVariables": "error",
|
|
36
|
+
"useExhaustiveDependencies": "warn"
|
|
37
|
+
},
|
|
38
|
+
"style": {
|
|
39
|
+
"noNonNullAssertion": "warn",
|
|
40
|
+
"useConst": "error",
|
|
41
|
+
"useTemplate": "error",
|
|
42
|
+
"useConsistentArrayType": { "level": "error", "options": { "syntax": "shorthand" } }
|
|
43
|
+
},
|
|
44
|
+
"suspicious": {
|
|
45
|
+
"noExplicitAny": "error",
|
|
46
|
+
"noConsoleLog": "warn"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"files": {
|
|
51
|
+
"ignore": ["node_modules", "dist", "build", ".next", "coverage"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// Fallback for projects not using Biome. Biome is the recommended single tool (see tooling/biome.md).
|
|
3
|
+
import tseslint from "@typescript-eslint/eslint-plugin";
|
|
4
|
+
import tsParser from "@typescript-eslint/parser";
|
|
5
|
+
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
6
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
7
|
+
|
|
8
|
+
/** @type {import("eslint").Linter.Config[]} */
|
|
9
|
+
const config = [
|
|
10
|
+
{
|
|
11
|
+
files: ["**/*.{ts,tsx}"],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parser: tsParser,
|
|
14
|
+
parserOptions: {
|
|
15
|
+
projectService: true,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
plugins: {
|
|
19
|
+
"@typescript-eslint": tseslint,
|
|
20
|
+
"react-hooks": reactHooks,
|
|
21
|
+
"jsx-a11y": jsxA11y,
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
// TypeScript
|
|
25
|
+
...tseslint.configs["recommended-type-checked"].rules,
|
|
26
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
27
|
+
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
28
|
+
"@typescript-eslint/consistent-type-imports": ["error", { prefer: "type-imports" }],
|
|
29
|
+
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
|
|
30
|
+
"@typescript-eslint/no-non-null-assertion": "warn",
|
|
31
|
+
"@typescript-eslint/prefer-nullish-coalescing": "error",
|
|
32
|
+
"@typescript-eslint/prefer-optional-chain": "error",
|
|
33
|
+
|
|
34
|
+
// Function style — prefer function declarations for named, module-level functions.
|
|
35
|
+
// Anonymous arrow callbacks (e.g. arr.map((x) => x)) are unaffected by this rule.
|
|
36
|
+
"func-style": ["error", "declaration"],
|
|
37
|
+
|
|
38
|
+
// React Hooks
|
|
39
|
+
...reactHooks.configs.recommended.rules,
|
|
40
|
+
|
|
41
|
+
// Accessibility
|
|
42
|
+
...jsxA11y.configs.recommended.rules,
|
|
43
|
+
|
|
44
|
+
// General
|
|
45
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
46
|
+
"prefer-const": "error",
|
|
47
|
+
"no-var": "error",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
52
|
+
rules: {
|
|
53
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
ignores: ["node_modules", "dist", "build", ".next", "coverage"],
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
export default config;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# [Project Name]
|
|
2
|
+
|
|
3
|
+
<!-- One sentence describing what this project is and who it is for -->
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js v22+
|
|
10
|
+
- pnpm v9+
|
|
11
|
+
|
|
12
|
+
### Install and Run
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm install
|
|
16
|
+
cp .env.example .env.local
|
|
17
|
+
# Fill in required values in .env.local
|
|
18
|
+
pnpm dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
App runs at [http://localhost:3000](http://localhost:3000).
|
|
22
|
+
|
|
23
|
+
## Development Commands
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm dev # start development server
|
|
27
|
+
pnpm build # production build
|
|
28
|
+
pnpm preview # preview production build locally
|
|
29
|
+
pnpm test # run unit and integration tests
|
|
30
|
+
pnpm test:e2e # run Playwright end-to-end tests
|
|
31
|
+
pnpm typecheck # TypeScript type checking
|
|
32
|
+
pnpm lint # Biome linting
|
|
33
|
+
pnpm format # Biome formatting
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Project Structure
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
src/
|
|
40
|
+
features/ # feature modules (colocated components, hooks, schemas, tests)
|
|
41
|
+
shared/ # reusable components, hooks, utils (used by 3+ features)
|
|
42
|
+
lib/ # third-party adapters (db, auth, email)
|
|
43
|
+
app/ # routing, layout, providers
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
See [CLAUDE.md](CLAUDE.md) for AI agent configuration and engineering standards.
|
|
47
|
+
|
|
48
|
+
## Tech Stack
|
|
49
|
+
|
|
50
|
+
| Area | Tool |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Framework | <!-- Next.js / Remix / Vite --> |
|
|
53
|
+
| Language | TypeScript (strict) |
|
|
54
|
+
| Styling | Tailwind CSS + shadcn/ui |
|
|
55
|
+
| Data fetching | TanStack Query |
|
|
56
|
+
| Forms | TanStack Form / React Hook Form |
|
|
57
|
+
| Validation | Zod |
|
|
58
|
+
| Testing | Vitest + Testing Library + Playwright |
|
|
59
|
+
| Linting | Biome |
|
|
60
|
+
| ORM | <!-- Prisma / Drizzle --> |
|
|
61
|
+
|
|
62
|
+
## Environment Variables
|
|
63
|
+
|
|
64
|
+
| Variable | Required | Description |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `DATABASE_URL` | Yes | PostgreSQL connection string |
|
|
67
|
+
| `VITE_API_BASE_URL` | Yes | Public API base URL |
|
|
68
|
+
|
|
69
|
+
See `.env.example` for all required variables.
|
|
70
|
+
|
|
71
|
+
## Contributing
|
|
72
|
+
|
|
73
|
+
1. Branch from `main`
|
|
74
|
+
2. Open a draft PR early for visibility
|
|
75
|
+
3. Ensure `pnpm typecheck`, `pnpm lint`, and `pnpm test` pass
|
|
76
|
+
4. Request review when ready
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? Why? (2–3 bullet points) -->
|
|
4
|
+
|
|
5
|
+
-
|
|
6
|
+
-
|
|
7
|
+
|
|
8
|
+
## Type of Change
|
|
9
|
+
|
|
10
|
+
- [ ] Bug fix
|
|
11
|
+
- [ ] New feature
|
|
12
|
+
- [ ] Refactor (no behavior change)
|
|
13
|
+
- [ ] Documentation
|
|
14
|
+
- [ ] Dependency update
|
|
15
|
+
- [ ] Infrastructure / tooling
|
|
16
|
+
|
|
17
|
+
## Test Plan
|
|
18
|
+
|
|
19
|
+
<!-- How did you verify this works? What edge cases did you test? -->
|
|
20
|
+
|
|
21
|
+
- [ ] Tested locally
|
|
22
|
+
- [ ] Unit / integration tests added or updated
|
|
23
|
+
- [ ] E2E tests added or updated (if critical flow)
|
|
24
|
+
- [ ] Tested on mobile / small screen (if UI change)
|
|
25
|
+
- [ ] Tested keyboard navigation (if interactive UI)
|
|
26
|
+
- [ ] Tested with a screen reader (if significant UI change)
|
|
27
|
+
|
|
28
|
+
## Checklist
|
|
29
|
+
|
|
30
|
+
- [ ] `pnpm typecheck` passes
|
|
31
|
+
- [ ] `pnpm lint` passes
|
|
32
|
+
- [ ] `pnpm test` passes
|
|
33
|
+
- [ ] No new `any` types
|
|
34
|
+
- [ ] No new `useEffect` for derived state or data fetching
|
|
35
|
+
- [ ] Accessible markup (semantic HTML, labels, keyboard navigable)
|
|
36
|
+
- [ ] No secrets or sensitive data committed
|
|
37
|
+
- [ ] `.env.example` updated (if new env var added)
|
|
38
|
+
- [ ] Documentation updated (if behavior changed)
|
|
39
|
+
|
|
40
|
+
## Screenshots
|
|
41
|
+
|
|
42
|
+
<!-- Add screenshots or recordings for UI changes -->
|
|
43
|
+
|
|
44
|
+
## Notes for Reviewer
|
|
45
|
+
|
|
46
|
+
<!-- Anything the reviewer should know — decisions made, things to pay attention to, known limitations -->
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"strict": true,
|
|
5
|
+
"noUnusedLocals": true,
|
|
6
|
+
"noUnusedParameters": true,
|
|
7
|
+
"noUncheckedIndexedAccess": true,
|
|
8
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
9
|
+
"noFallthroughCasesInSwitch": true,
|
|
10
|
+
"allowUnreachableCode": false,
|
|
11
|
+
"allowUnusedLabels": false,
|
|
12
|
+
"noUncheckedSideEffectImports": true,
|
|
13
|
+
"erasableSyntaxOnly": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"skipLibCheck": true,
|
|
18
|
+
"moduleDetection": "force",
|
|
19
|
+
"target": "ES2022",
|
|
20
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
21
|
+
"module": "ESNext",
|
|
22
|
+
"moduleResolution": "bundler",
|
|
23
|
+
"resolveJsonModule": true,
|
|
24
|
+
"jsx": "react-jsx",
|
|
25
|
+
"declaration": true,
|
|
26
|
+
"declarationMap": true,
|
|
27
|
+
"sourceMap": true,
|
|
28
|
+
"baseUrl": ".",
|
|
29
|
+
"paths": {
|
|
30
|
+
"~/*": ["./src/*"]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"include": ["src/**/*", "vite.config.ts"],
|
|
34
|
+
"exclude": ["node_modules", "dist", "build", "coverage"]
|
|
35
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Biome
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Biome replaces both ESLint and Prettier with a single fast tool. It handles formatting, linting, and import organization.
|
|
6
|
+
|
|
7
|
+
## Why Biome
|
|
8
|
+
|
|
9
|
+
- 10–100× faster than ESLint + Prettier
|
|
10
|
+
- Single config, single tool, single install
|
|
11
|
+
- Zero-conflict formatting (no Prettier vs. ESLint format fights)
|
|
12
|
+
- Built-in import organizer
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add --save-dev --save-exact @biomejs/biome
|
|
18
|
+
pnpm biome init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or copy [`templates/biome.json`](../templates/biome.json) into your project as a starting point.
|
|
22
|
+
|
|
23
|
+
## Key Commands
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Check (lint + format check, no writes)
|
|
27
|
+
pnpm biome check .
|
|
28
|
+
|
|
29
|
+
# Format files
|
|
30
|
+
pnpm biome format --write .
|
|
31
|
+
|
|
32
|
+
# Lint files
|
|
33
|
+
pnpm biome lint .
|
|
34
|
+
|
|
35
|
+
# Fix lint + format in one pass
|
|
36
|
+
pnpm biome check --write .
|
|
37
|
+
|
|
38
|
+
# CI — no writes, exit non-zero on error
|
|
39
|
+
pnpm biome ci .
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## CI Integration
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
# .github/workflows/ci.yml
|
|
46
|
+
- name: Biome check
|
|
47
|
+
run: pnpm biome ci .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`biome ci` is equivalent to `biome check` but never writes files and always exits non-zero on any finding.
|
|
51
|
+
|
|
52
|
+
## Editor Integration
|
|
53
|
+
|
|
54
|
+
Install the Biome VS Code extension: `biomejs.biome`
|
|
55
|
+
|
|
56
|
+
Enable format on save:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
// .vscode/settings.json
|
|
60
|
+
{
|
|
61
|
+
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
62
|
+
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
63
|
+
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
64
|
+
"[json]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
65
|
+
"editor.formatOnSave": true
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Config Reference
|
|
70
|
+
|
|
71
|
+
See [`templates/biome.json`](../templates/biome.json) for the canonical Biome config.
|
|
72
|
+
|
|
73
|
+
## Migrating from ESLint + Prettier
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pnpm biome migrate eslint --include-inspired
|
|
77
|
+
pnpm biome migrate prettier
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Biome can automatically migrate most ESLint and Prettier configs.
|
|
81
|
+
|
|
82
|
+
## DO NOT
|
|
83
|
+
|
|
84
|
+
- Run both Biome and Prettier on the same files — they will conflict
|
|
85
|
+
- Disable rules with `// biome-ignore` without a specific comment explaining why
|
|
86
|
+
- Skip `biome ci` in CI pipelines
|
|
87
|
+
|
|
88
|
+
## See Also
|
|
89
|
+
|
|
90
|
+
- [`ci.md`](ci.md) — `biome ci` as the gating command
|
|
91
|
+
- [`dependencies.md`](dependencies.md) — replacing ESLint + Prettier
|
|
92
|
+
- [`vite.md`](vite.md) — editor integration
|