agent-bober 0.1.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/.claude-plugin/plugin.json +9 -0
- package/LICENSE +21 -0
- package/README.md +495 -0
- package/agents/bober-evaluator.md +323 -0
- package/agents/bober-generator.md +245 -0
- package/agents/bober-planner.md +248 -0
- package/dist/cli/commands/eval.d.ts +6 -0
- package/dist/cli/commands/eval.d.ts.map +1 -0
- package/dist/cli/commands/eval.js +129 -0
- package/dist/cli/commands/eval.js.map +1 -0
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +547 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +5 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +87 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/run.d.ts +5 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +120 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/sprint.d.ts +6 -0
- package/dist/cli/commands/sprint.d.ts.map +1 -0
- package/dist/cli/commands/sprint.js +206 -0
- package/dist/cli/commands/sprint.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +124 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/defaults.d.ts +15 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +226 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +8 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +18 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +904 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +181 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/contracts/eval-result.d.ts +205 -0
- package/dist/contracts/eval-result.d.ts.map +1 -0
- package/dist/contracts/eval-result.js +87 -0
- package/dist/contracts/eval-result.js.map +1 -0
- package/dist/contracts/index.d.ts +4 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +16 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/spec.d.ts +101 -0
- package/dist/contracts/spec.d.ts.map +1 -0
- package/dist/contracts/spec.js +51 -0
- package/dist/contracts/spec.js.map +1 -0
- package/dist/contracts/sprint-contract.d.ts +141 -0
- package/dist/contracts/sprint-contract.d.ts.map +1 -0
- package/dist/contracts/sprint-contract.js +80 -0
- package/dist/contracts/sprint-contract.js.map +1 -0
- package/dist/evaluators/builtin/api-check.d.ts +13 -0
- package/dist/evaluators/builtin/api-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/api-check.js +152 -0
- package/dist/evaluators/builtin/api-check.js.map +1 -0
- package/dist/evaluators/builtin/build-check.d.ts +17 -0
- package/dist/evaluators/builtin/build-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/build-check.js +155 -0
- package/dist/evaluators/builtin/build-check.js.map +1 -0
- package/dist/evaluators/builtin/command-runner.d.ts +26 -0
- package/dist/evaluators/builtin/command-runner.d.ts.map +1 -0
- package/dist/evaluators/builtin/command-runner.js +114 -0
- package/dist/evaluators/builtin/command-runner.js.map +1 -0
- package/dist/evaluators/builtin/lint.d.ts +17 -0
- package/dist/evaluators/builtin/lint.d.ts.map +1 -0
- package/dist/evaluators/builtin/lint.js +264 -0
- package/dist/evaluators/builtin/lint.js.map +1 -0
- package/dist/evaluators/builtin/playwright.d.ts +16 -0
- package/dist/evaluators/builtin/playwright.d.ts.map +1 -0
- package/dist/evaluators/builtin/playwright.js +238 -0
- package/dist/evaluators/builtin/playwright.js.map +1 -0
- package/dist/evaluators/builtin/typescript-check.d.ts +12 -0
- package/dist/evaluators/builtin/typescript-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/typescript-check.js +155 -0
- package/dist/evaluators/builtin/typescript-check.js.map +1 -0
- package/dist/evaluators/builtin/unit-test.d.ts +18 -0
- package/dist/evaluators/builtin/unit-test.d.ts.map +1 -0
- package/dist/evaluators/builtin/unit-test.js +279 -0
- package/dist/evaluators/builtin/unit-test.js.map +1 -0
- package/dist/evaluators/index.d.ts +11 -0
- package/dist/evaluators/index.d.ts.map +1 -0
- package/dist/evaluators/index.js +13 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/plugin-interface.d.ts +50 -0
- package/dist/evaluators/plugin-interface.d.ts.map +1 -0
- package/dist/evaluators/plugin-interface.js +2 -0
- package/dist/evaluators/plugin-interface.js.map +1 -0
- package/dist/evaluators/plugin-loader.d.ts +18 -0
- package/dist/evaluators/plugin-loader.d.ts.map +1 -0
- package/dist/evaluators/plugin-loader.js +107 -0
- package/dist/evaluators/plugin-loader.js.map +1 -0
- package/dist/evaluators/registry.d.ts +78 -0
- package/dist/evaluators/registry.d.ts.map +1 -0
- package/dist/evaluators/registry.js +238 -0
- package/dist/evaluators/registry.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator/context-handoff.d.ts +543 -0
- package/dist/orchestrator/context-handoff.d.ts.map +1 -0
- package/dist/orchestrator/context-handoff.js +133 -0
- package/dist/orchestrator/context-handoff.js.map +1 -0
- package/dist/orchestrator/evaluator-agent.d.ts +15 -0
- package/dist/orchestrator/evaluator-agent.d.ts.map +1 -0
- package/dist/orchestrator/evaluator-agent.js +233 -0
- package/dist/orchestrator/evaluator-agent.js.map +1 -0
- package/dist/orchestrator/generator-agent.d.ts +16 -0
- package/dist/orchestrator/generator-agent.d.ts.map +1 -0
- package/dist/orchestrator/generator-agent.js +147 -0
- package/dist/orchestrator/generator-agent.js.map +1 -0
- package/dist/orchestrator/pipeline.d.ts +24 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -0
- package/dist/orchestrator/pipeline.js +290 -0
- package/dist/orchestrator/pipeline.js.map +1 -0
- package/dist/orchestrator/planner-agent.d.ts +10 -0
- package/dist/orchestrator/planner-agent.d.ts.map +1 -0
- package/dist/orchestrator/planner-agent.js +187 -0
- package/dist/orchestrator/planner-agent.js.map +1 -0
- package/dist/state/helpers.d.ts +5 -0
- package/dist/state/helpers.d.ts.map +1 -0
- package/dist/state/helpers.js +8 -0
- package/dist/state/helpers.js.map +1 -0
- package/dist/state/history.d.ts +39 -0
- package/dist/state/history.d.ts.map +1 -0
- package/dist/state/history.js +162 -0
- package/dist/state/history.js.map +1 -0
- package/dist/state/index.d.ts +8 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +22 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/plan-state.d.ts +21 -0
- package/dist/state/plan-state.d.ts.map +1 -0
- package/dist/state/plan-state.js +108 -0
- package/dist/state/plan-state.js.map +1 -0
- package/dist/state/sprint-state.d.ts +20 -0
- package/dist/state/sprint-state.d.ts.map +1 -0
- package/dist/state/sprint-state.js +98 -0
- package/dist/state/sprint-state.js.map +1 -0
- package/dist/utils/fs.d.ts +31 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +67 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/git.d.ts +35 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +84 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +73 -0
- package/dist/utils/logger.js.map +1 -0
- package/hooks/hooks.json +10 -0
- package/package.json +67 -0
- package/scripts/detect-stack.sh +287 -0
- package/scripts/init-project.sh +206 -0
- package/scripts/run-eval.sh +175 -0
- package/skills/bober.anchor/SKILL.md +365 -0
- package/skills/bober.anchor/references/anchor-guide.md +567 -0
- package/skills/bober.brownfield/SKILL.md +422 -0
- package/skills/bober.brownfield/references/codebase-analysis.md +304 -0
- package/skills/bober.eval/SKILL.md +235 -0
- package/skills/bober.eval/references/eval-strategies.md +407 -0
- package/skills/bober.eval/references/feedback-format.md +182 -0
- package/skills/bober.plan/SKILL.md +244 -0
- package/skills/bober.plan/references/clarification-guide.md +124 -0
- package/skills/bober.plan/references/spec-schema.md +253 -0
- package/skills/bober.react/SKILL.md +330 -0
- package/skills/bober.react/references/react-scaffold.md +344 -0
- package/skills/bober.run/SKILL.md +303 -0
- package/skills/bober.solidity/SKILL.md +416 -0
- package/skills/bober.solidity/references/solidity-guide.md +487 -0
- package/skills/bober.sprint/SKILL.md +280 -0
- package/skills/bober.sprint/references/contract-schema.md +251 -0
- package/templates/base/CLAUDE.md +20 -0
- package/templates/base/bober.config.json +35 -0
- package/templates/brownfield/CLAUDE.md +34 -0
- package/templates/brownfield/bober.config.json +37 -0
- package/templates/presets/anchor/CLAUDE.md +163 -0
- package/templates/presets/anchor/bober.config.json +9 -0
- package/templates/presets/api-node/CLAUDE.md +153 -0
- package/templates/presets/api-node/bober.config.json +10 -0
- package/templates/presets/nextjs/CLAUDE.md +82 -0
- package/templates/presets/nextjs/bober.config.json +14 -0
- package/templates/presets/python-api/CLAUDE.md +202 -0
- package/templates/presets/python-api/bober.config.json +9 -0
- package/templates/presets/react-vite/CLAUDE.md +71 -0
- package/templates/presets/react-vite/bober.config.json +53 -0
- package/templates/presets/react-vite/scaffold/package.json +45 -0
- package/templates/presets/react-vite/scaffold/server/index.ts +38 -0
- package/templates/presets/react-vite/scaffold/server/tsconfig.json +24 -0
- package/templates/presets/react-vite/scaffold/src/App.tsx +37 -0
- package/templates/presets/react-vite/scaffold/src/index.html +12 -0
- package/templates/presets/react-vite/scaffold/src/main.tsx +12 -0
- package/templates/presets/react-vite/scaffold/tsconfig.json +27 -0
- package/templates/presets/react-vite/scaffold/vite.config.ts +34 -0
- package/templates/presets/solidity/CLAUDE.md +106 -0
- package/templates/presets/solidity/bober.config.json +9 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bober.react
|
|
3
|
+
description: React-based web application workflow — scaffold, plan, and build React apps with Vite or Next.js, optional backend, and database. This is one of several specialized workflows; use it specifically for React-based web applications.
|
|
4
|
+
argument-hint: <app-description>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# bober.react — React Web Application Workflow
|
|
8
|
+
|
|
9
|
+
You are running the **bober.react** skill. This is a specialized workflow for building React-based web applications. It combines project scaffolding, planning, and execution optimized for the React ecosystem. For other project types (smart contracts, APIs, CLI tools, etc.), use the appropriate specialized skill or the generic `bober.run` pipeline.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
Use `bober.react` when:
|
|
14
|
+
- Building a new React-based web application from scratch (greenfield)
|
|
15
|
+
- Adding a major feature to an existing React application
|
|
16
|
+
- The project involves: React frontend, optionally with an API backend and/or database
|
|
17
|
+
|
|
18
|
+
## Stack Assumptions
|
|
19
|
+
|
|
20
|
+
This skill is optimized for:
|
|
21
|
+
- **Frontend:** React 18+ with Vite (or Next.js), TypeScript
|
|
22
|
+
- **Backend:** Node.js with Express/Fastify/Hono, OR Python with FastAPI/Flask
|
|
23
|
+
- **Database:** SQLite (development) / PostgreSQL (production), with Prisma/Drizzle ORM
|
|
24
|
+
- **Styling:** Tailwind CSS (preferred), CSS Modules, or styled-components
|
|
25
|
+
- **Testing:** Vitest (unit), Playwright (E2E)
|
|
26
|
+
- **State Management:** React built-in (useState/useContext) for simple apps, Zustand/TanStack Query for complex apps
|
|
27
|
+
|
|
28
|
+
If the user's stack differs, adapt accordingly. These are defaults, not requirements.
|
|
29
|
+
|
|
30
|
+
## Step 1: Project Assessment
|
|
31
|
+
|
|
32
|
+
### Greenfield (New Project)
|
|
33
|
+
|
|
34
|
+
If there is no `package.json` or the project directory is empty:
|
|
35
|
+
|
|
36
|
+
1. Ask the user to describe their application
|
|
37
|
+
2. Ask clarifying questions specific to React apps:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
**Q1: Frontend Framework**
|
|
41
|
+
A) Vite + React (recommended for SPAs and most apps)
|
|
42
|
+
B) Next.js (if you need SSR, static generation, or file-based routing)
|
|
43
|
+
C) Remix (if you want full-stack React with nested routing)
|
|
44
|
+
|
|
45
|
+
**Q2: Backend**
|
|
46
|
+
A) Express.js (Node.js, most common, largest ecosystem)
|
|
47
|
+
B) Fastify (Node.js, faster, schema-based validation)
|
|
48
|
+
C) Hono (lightweight, edge-ready)
|
|
49
|
+
D) FastAPI (Python, if you prefer Python backend)
|
|
50
|
+
E) No separate backend (use Next.js API routes or similar)
|
|
51
|
+
|
|
52
|
+
**Q3: Database**
|
|
53
|
+
A) SQLite with Prisma (simple, zero setup, great for prototyping)
|
|
54
|
+
B) PostgreSQL with Prisma (production-ready, recommended for real apps)
|
|
55
|
+
C) PostgreSQL with Drizzle (lighter ORM, SQL-like API)
|
|
56
|
+
D) No database (frontend only or external API)
|
|
57
|
+
|
|
58
|
+
**Q4: UI Approach**
|
|
59
|
+
A) Tailwind CSS + shadcn/ui (modern, utility-first, great component library)
|
|
60
|
+
B) Tailwind CSS only (utility-first, no component library)
|
|
61
|
+
C) CSS Modules (scoped styles, no utility classes)
|
|
62
|
+
D) I have a specific design system in mind (please describe)
|
|
63
|
+
|
|
64
|
+
**Q5: Authentication**
|
|
65
|
+
A) Email + password (built-in, using bcrypt + sessions)
|
|
66
|
+
B) OAuth (Google, GitHub, etc.) via a library like next-auth or lucia
|
|
67
|
+
C) No authentication needed for now
|
|
68
|
+
D) I'll specify my auth requirements
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. After answers, scaffold the project using the reference structure documented in `skills/bober.react/references/react-scaffold.md`
|
|
72
|
+
|
|
73
|
+
### Brownfield (Existing React Project)
|
|
74
|
+
|
|
75
|
+
If `package.json` exists with React:
|
|
76
|
+
|
|
77
|
+
1. Analyze the existing stack:
|
|
78
|
+
- Read `package.json` for dependencies
|
|
79
|
+
- Check for routing: `react-router-dom`, `next`, file-based routing
|
|
80
|
+
- Check for state management: `zustand`, `redux`, `@tanstack/react-query`, `recoil`
|
|
81
|
+
- Check for styling: `tailwindcss`, `styled-components`, `@emotion`, CSS Modules
|
|
82
|
+
- Check for ORM/database: `prisma`, `drizzle-orm`, `mongoose`, `knex`
|
|
83
|
+
- Check for testing: `vitest`, `jest`, `playwright`, `cypress`
|
|
84
|
+
- Check for UI libraries: `@radix-ui`, `@shadcn`, `@mui`, `@chakra-ui`
|
|
85
|
+
|
|
86
|
+
2. Read key configuration files:
|
|
87
|
+
- `vite.config.ts` or `next.config.js`
|
|
88
|
+
- `tailwind.config.ts`
|
|
89
|
+
- `prisma/schema.prisma` or `drizzle/schema.ts`
|
|
90
|
+
- `playwright.config.ts`
|
|
91
|
+
|
|
92
|
+
3. Survey the project structure to understand conventions
|
|
93
|
+
|
|
94
|
+
4. Skip scaffolding -- proceed directly to planning
|
|
95
|
+
|
|
96
|
+
## Step 2: Initialize Configuration
|
|
97
|
+
|
|
98
|
+
Create or update `bober.config.json` with React-optimized defaults:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"project": {
|
|
103
|
+
"name": "<project-name>",
|
|
104
|
+
"mode": "greenfield",
|
|
105
|
+
"preset": "react-vite",
|
|
106
|
+
"description": "<user's app description>"
|
|
107
|
+
},
|
|
108
|
+
"planner": {
|
|
109
|
+
"maxClarifications": 5,
|
|
110
|
+
"model": "opus",
|
|
111
|
+
"contextFiles": [
|
|
112
|
+
"package.json",
|
|
113
|
+
"tsconfig.json",
|
|
114
|
+
"vite.config.ts",
|
|
115
|
+
"prisma/schema.prisma",
|
|
116
|
+
"src/App.tsx"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"generator": {
|
|
120
|
+
"model": "sonnet",
|
|
121
|
+
"maxTurnsPerSprint": 50,
|
|
122
|
+
"autoCommit": true,
|
|
123
|
+
"branchPattern": "bober/{feature-name}"
|
|
124
|
+
},
|
|
125
|
+
"evaluator": {
|
|
126
|
+
"model": "sonnet",
|
|
127
|
+
"strategies": [
|
|
128
|
+
{ "type": "build", "required": true },
|
|
129
|
+
{ "type": "typecheck", "required": true },
|
|
130
|
+
{ "type": "lint", "required": true },
|
|
131
|
+
{ "type": "unit-test", "required": true },
|
|
132
|
+
{ "type": "playwright", "required": false }
|
|
133
|
+
],
|
|
134
|
+
"maxIterations": 3
|
|
135
|
+
},
|
|
136
|
+
"sprint": {
|
|
137
|
+
"maxSprints": 10,
|
|
138
|
+
"requireContracts": true,
|
|
139
|
+
"sprintSize": "medium"
|
|
140
|
+
},
|
|
141
|
+
"pipeline": {
|
|
142
|
+
"maxIterations": 20,
|
|
143
|
+
"requireApproval": false,
|
|
144
|
+
"contextReset": "always"
|
|
145
|
+
},
|
|
146
|
+
"commands": {
|
|
147
|
+
"install": "npm install",
|
|
148
|
+
"build": "npm run build",
|
|
149
|
+
"test": "npx vitest run",
|
|
150
|
+
"lint": "npm run lint",
|
|
151
|
+
"typecheck": "npx tsc --noEmit",
|
|
152
|
+
"dev": "npm run dev"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Adjust commands based on what actually exists in `package.json` scripts. If using Next.js, set `"preset": "nextjs"` instead of `"react-vite"` and adjust context files and commands accordingly (e.g., `next.config.js` instead of `vite.config.ts`).
|
|
158
|
+
|
|
159
|
+
## Step 3: Scaffold (Greenfield Only)
|
|
160
|
+
|
|
161
|
+
For new projects, create the initial project structure. Reference `skills/bober.react/references/react-scaffold.md` for the full scaffold specification.
|
|
162
|
+
|
|
163
|
+
**Scaffolding steps:**
|
|
164
|
+
|
|
165
|
+
1. **Initialize the project:**
|
|
166
|
+
```bash
|
|
167
|
+
npm create vite@latest . -- --template react-ts
|
|
168
|
+
```
|
|
169
|
+
Or if using Next.js:
|
|
170
|
+
```bash
|
|
171
|
+
npx create-next-app@latest . --typescript --tailwind --eslint --app --src-dir
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
2. **Install core dependencies based on user choices:**
|
|
175
|
+
- ORM: `prisma` + `@prisma/client` or `drizzle-orm` + `drizzle-kit`
|
|
176
|
+
- Styling: `tailwindcss` + `postcss` + `autoprefixer` (if Tailwind)
|
|
177
|
+
- UI components: `@shadcn/ui` dependencies if chosen
|
|
178
|
+
- Auth: `bcrypt` + `express-session` or `lucia` or `next-auth`
|
|
179
|
+
- Backend: `express` + `cors` + `helmet` or `fastify`
|
|
180
|
+
|
|
181
|
+
3. **Create the project structure:**
|
|
182
|
+
- See the full scaffold reference for directory layout
|
|
183
|
+
- Create placeholder files for the core architecture
|
|
184
|
+
|
|
185
|
+
4. **Configure TypeScript, ESLint, and Tailwind**
|
|
186
|
+
|
|
187
|
+
5. **Set up the database:**
|
|
188
|
+
```bash
|
|
189
|
+
npx prisma init --datasource-provider sqlite
|
|
190
|
+
```
|
|
191
|
+
Or equivalent for the chosen ORM
|
|
192
|
+
|
|
193
|
+
6. **Set up testing:**
|
|
194
|
+
```bash
|
|
195
|
+
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
|
|
196
|
+
npm install -D playwright @playwright/test
|
|
197
|
+
npx playwright install chromium
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
7. **Create initial git commit:**
|
|
201
|
+
```bash
|
|
202
|
+
git init
|
|
203
|
+
git add -A
|
|
204
|
+
git commit -m "chore: initial scaffold from bober.react"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
8. **Verify the scaffold builds:**
|
|
208
|
+
```bash
|
|
209
|
+
npm run build
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Step 4: Plan the Feature
|
|
213
|
+
|
|
214
|
+
Run the full planning workflow (same as `bober.plan`) with React-specific enhancements:
|
|
215
|
+
|
|
216
|
+
### React-Specific Planning Guidance
|
|
217
|
+
|
|
218
|
+
When decomposing into sprints, follow these React-specific patterns:
|
|
219
|
+
|
|
220
|
+
**Sprint ordering for a typical React feature:**
|
|
221
|
+
1. **Data layer first:** Database schema, API endpoints, data validation
|
|
222
|
+
2. **Core UI components:** The main components that render data
|
|
223
|
+
3. **Interactivity:** Forms, mutations, optimistic updates
|
|
224
|
+
4. **Navigation and routing:** New routes, navigation links, breadcrumbs
|
|
225
|
+
5. **Polish:** Loading states, error boundaries, empty states, responsive design
|
|
226
|
+
|
|
227
|
+
**React-specific success criteria to include:**
|
|
228
|
+
- "The component renders without React console errors or warnings"
|
|
229
|
+
- "The page is accessible: all interactive elements have ARIA labels, forms have proper labels, focus management works"
|
|
230
|
+
- "Client-side routing works: navigating to /<route> renders the component without a full page reload"
|
|
231
|
+
- "Form submission handles loading state (submit button disabled during request) and error state (error message displayed on failure)"
|
|
232
|
+
- "The component correctly handles empty data state (no items to display)"
|
|
233
|
+
- "API errors are caught and displayed to the user, not as unhandled exceptions"
|
|
234
|
+
|
|
235
|
+
**React-specific evaluator notes:**
|
|
236
|
+
- For component rendering criteria, the evaluator should check for the component file, verify it exports a React component, and check that it handles the key states (loading, error, empty, populated)
|
|
237
|
+
- For routing criteria, check `App.tsx` or the router configuration for the new route
|
|
238
|
+
- For state management criteria, verify the state management approach matches the existing pattern in the codebase
|
|
239
|
+
- For API integration criteria, verify the API call uses the project's HTTP client (fetch, axios, etc.) and handles errors
|
|
240
|
+
|
|
241
|
+
## Step 5: Execute the Pipeline
|
|
242
|
+
|
|
243
|
+
Run the full sprint execution loop (same as `bober.run`) with React-specific evaluation:
|
|
244
|
+
|
|
245
|
+
### React-Specific Evaluation Enhancements
|
|
246
|
+
|
|
247
|
+
When evaluating React sprints, the evaluator should additionally check:
|
|
248
|
+
|
|
249
|
+
1. **Component structure:**
|
|
250
|
+
- Components are in the correct directory
|
|
251
|
+
- Components follow the project's naming convention (PascalCase for components)
|
|
252
|
+
- Components are properly typed (props interface/type defined)
|
|
253
|
+
|
|
254
|
+
2. **React patterns:**
|
|
255
|
+
- Hooks are used correctly (no conditional hooks, proper dependency arrays)
|
|
256
|
+
- Side effects are in `useEffect` with proper cleanup
|
|
257
|
+
- Expensive computations use `useMemo`/`useCallback` where appropriate
|
|
258
|
+
- State is at the correct level (not too high, not too low)
|
|
259
|
+
|
|
260
|
+
3. **Accessibility:**
|
|
261
|
+
- Interactive elements are keyboard accessible
|
|
262
|
+
- Form inputs have labels
|
|
263
|
+
- Images have alt text
|
|
264
|
+
- Color contrast is sufficient (if Tailwind, check class choices)
|
|
265
|
+
- Focus management on route changes
|
|
266
|
+
|
|
267
|
+
4. **Performance basics:**
|
|
268
|
+
- No unnecessary re-renders from unstable references
|
|
269
|
+
- Lists use proper `key` props (not array index for dynamic lists)
|
|
270
|
+
- Large data sets use pagination or virtualization
|
|
271
|
+
- Images are optimized (lazy loading, proper sizing)
|
|
272
|
+
|
|
273
|
+
5. **Error handling:**
|
|
274
|
+
- Error boundaries exist for route-level components
|
|
275
|
+
- API errors are caught and displayed
|
|
276
|
+
- Loading states are implemented (not just blank screens)
|
|
277
|
+
- Form validation provides clear feedback
|
|
278
|
+
|
|
279
|
+
## Step 6: Post-Pipeline Verification
|
|
280
|
+
|
|
281
|
+
After all sprints pass, run a final comprehensive check:
|
|
282
|
+
|
|
283
|
+
1. **Full build:**
|
|
284
|
+
```bash
|
|
285
|
+
npm run build
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
2. **Full test suite:**
|
|
289
|
+
```bash
|
|
290
|
+
npm test
|
|
291
|
+
npx playwright test # if configured
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
3. **Dev server smoke test:**
|
|
295
|
+
- Start the dev server
|
|
296
|
+
- Verify the app loads at the root URL
|
|
297
|
+
- Navigate to the new routes
|
|
298
|
+
- Verify no console errors
|
|
299
|
+
|
|
300
|
+
4. **Report to user:**
|
|
301
|
+
```
|
|
302
|
+
## React App Complete
|
|
303
|
+
|
|
304
|
+
Your app is ready for review.
|
|
305
|
+
|
|
306
|
+
### How to Run
|
|
307
|
+
npm run dev # Start development server
|
|
308
|
+
npm run build # Build for production
|
|
309
|
+
npm test # Run unit tests
|
|
310
|
+
npx playwright test # Run E2E tests (if configured)
|
|
311
|
+
|
|
312
|
+
### What Was Built
|
|
313
|
+
<Summary of features implemented>
|
|
314
|
+
|
|
315
|
+
### Project Structure
|
|
316
|
+
<Key new files and directories>
|
|
317
|
+
|
|
318
|
+
### Next Steps
|
|
319
|
+
- Review the code on branch: bober/<feature-slug>
|
|
320
|
+
- Test the app locally: npm run dev
|
|
321
|
+
- When satisfied, merge to main
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Error Handling
|
|
325
|
+
|
|
326
|
+
- **Vite/Next.js HMR issues:** If the dev server shows HMR errors during evaluation, restart the dev server before re-evaluating
|
|
327
|
+
- **Prisma migration issues:** If database schema changes fail, check if the database file is locked (SQLite) or if the migration conflicts with existing data
|
|
328
|
+
- **Playwright browser issues:** If Playwright cannot find a browser, run `npx playwright install chromium` as a setup step
|
|
329
|
+
- **Port conflicts:** If the dev server port is in use, detect this and either kill the existing process or use an alternative port
|
|
330
|
+
- **Node module resolution issues:** If imports fail after adding new dependencies, ensure `node_modules` is up to date with `npm install`
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# React + Backend Scaffold Reference
|
|
2
|
+
|
|
3
|
+
This document defines the standard project structure and configuration for React full-stack projects scaffolded by `bober.react`.
|
|
4
|
+
|
|
5
|
+
## Standard Directory Layout
|
|
6
|
+
|
|
7
|
+
### Vite + Express (Monorepo-Style)
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
project-root/
|
|
11
|
+
bober.config.json
|
|
12
|
+
package.json
|
|
13
|
+
tsconfig.json
|
|
14
|
+
vite.config.ts
|
|
15
|
+
tailwind.config.ts
|
|
16
|
+
postcss.config.js
|
|
17
|
+
.env.example
|
|
18
|
+
.gitignore
|
|
19
|
+
prisma/
|
|
20
|
+
schema.prisma
|
|
21
|
+
migrations/
|
|
22
|
+
src/
|
|
23
|
+
main.tsx # React entry point
|
|
24
|
+
App.tsx # Root component with router
|
|
25
|
+
index.css # Global styles (Tailwind directives)
|
|
26
|
+
vite-env.d.ts # Vite type declarations
|
|
27
|
+
components/
|
|
28
|
+
ui/ # Reusable UI primitives (Button, Input, Card, etc.)
|
|
29
|
+
layout/ # Layout components (Header, Sidebar, Footer)
|
|
30
|
+
pages/ # Route-level page components
|
|
31
|
+
Home.tsx
|
|
32
|
+
NotFound.tsx
|
|
33
|
+
hooks/ # Custom React hooks
|
|
34
|
+
lib/ # Shared utilities and helpers
|
|
35
|
+
api.ts # API client (fetch wrapper)
|
|
36
|
+
utils.ts # General utilities
|
|
37
|
+
cn.ts # classnames utility (if Tailwind)
|
|
38
|
+
types/ # Shared TypeScript types
|
|
39
|
+
index.ts
|
|
40
|
+
contexts/ # React contexts (if used)
|
|
41
|
+
server/
|
|
42
|
+
index.ts # Express app entry point
|
|
43
|
+
routes/ # API route handlers
|
|
44
|
+
index.ts # Route aggregator
|
|
45
|
+
middleware/ # Express middleware
|
|
46
|
+
errorHandler.ts
|
|
47
|
+
auth.ts # Auth middleware (if applicable)
|
|
48
|
+
services/ # Business logic layer
|
|
49
|
+
db/
|
|
50
|
+
client.ts # Prisma client instance
|
|
51
|
+
tests/
|
|
52
|
+
setup.ts # Test setup (vitest)
|
|
53
|
+
unit/ # Unit tests
|
|
54
|
+
e2e/ # Playwright E2E tests
|
|
55
|
+
example.spec.ts
|
|
56
|
+
public/
|
|
57
|
+
favicon.svg
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Next.js (App Router)
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
project-root/
|
|
64
|
+
bober.config.json
|
|
65
|
+
package.json
|
|
66
|
+
tsconfig.json
|
|
67
|
+
next.config.ts
|
|
68
|
+
tailwind.config.ts
|
|
69
|
+
postcss.config.js
|
|
70
|
+
.env.example
|
|
71
|
+
.gitignore
|
|
72
|
+
prisma/
|
|
73
|
+
schema.prisma
|
|
74
|
+
migrations/
|
|
75
|
+
src/
|
|
76
|
+
app/
|
|
77
|
+
layout.tsx # Root layout
|
|
78
|
+
page.tsx # Home page
|
|
79
|
+
globals.css # Global styles
|
|
80
|
+
not-found.tsx # 404 page
|
|
81
|
+
api/ # API routes
|
|
82
|
+
route.ts
|
|
83
|
+
components/
|
|
84
|
+
ui/ # Reusable UI primitives
|
|
85
|
+
layout/ # Layout components
|
|
86
|
+
hooks/ # Custom React hooks
|
|
87
|
+
lib/ # Shared utilities
|
|
88
|
+
api.ts
|
|
89
|
+
utils.ts
|
|
90
|
+
db.ts # Prisma client
|
|
91
|
+
types/ # Shared types
|
|
92
|
+
tests/
|
|
93
|
+
unit/
|
|
94
|
+
e2e/
|
|
95
|
+
public/
|
|
96
|
+
favicon.svg
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Key Configuration Files
|
|
100
|
+
|
|
101
|
+
### package.json (Vite + Express)
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"name": "<project-name>",
|
|
106
|
+
"private": true,
|
|
107
|
+
"version": "0.0.1",
|
|
108
|
+
"type": "module",
|
|
109
|
+
"scripts": {
|
|
110
|
+
"dev": "concurrently \"vite\" \"tsx watch server/index.ts\"",
|
|
111
|
+
"build": "tsc && vite build",
|
|
112
|
+
"preview": "vite preview",
|
|
113
|
+
"server": "tsx server/index.ts",
|
|
114
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
115
|
+
"typecheck": "tsc --noEmit",
|
|
116
|
+
"test": "vitest run",
|
|
117
|
+
"test:watch": "vitest",
|
|
118
|
+
"test:e2e": "playwright test",
|
|
119
|
+
"db:push": "prisma db push",
|
|
120
|
+
"db:migrate": "prisma migrate dev",
|
|
121
|
+
"db:studio": "prisma studio"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### tsconfig.json
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"compilerOptions": {
|
|
131
|
+
"target": "ES2022",
|
|
132
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
133
|
+
"module": "ESNext",
|
|
134
|
+
"moduleResolution": "bundler",
|
|
135
|
+
"strict": true,
|
|
136
|
+
"jsx": "react-jsx",
|
|
137
|
+
"esModuleInterop": true,
|
|
138
|
+
"skipLibCheck": true,
|
|
139
|
+
"forceConsistentCasingInFileNames": true,
|
|
140
|
+
"resolveJsonModule": true,
|
|
141
|
+
"isolatedModules": true,
|
|
142
|
+
"noEmit": true,
|
|
143
|
+
"baseUrl": ".",
|
|
144
|
+
"paths": {
|
|
145
|
+
"@/*": ["./src/*"],
|
|
146
|
+
"@server/*": ["./server/*"]
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"include": ["src", "server"],
|
|
150
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### vite.config.ts
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { defineConfig } from 'vite';
|
|
158
|
+
import react from '@vitejs/plugin-react';
|
|
159
|
+
import path from 'path';
|
|
160
|
+
|
|
161
|
+
export default defineConfig({
|
|
162
|
+
plugins: [react()],
|
|
163
|
+
resolve: {
|
|
164
|
+
alias: {
|
|
165
|
+
'@': path.resolve(__dirname, './src'),
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
server: {
|
|
169
|
+
proxy: {
|
|
170
|
+
'/api': {
|
|
171
|
+
target: 'http://localhost:3001',
|
|
172
|
+
changeOrigin: true,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### tailwind.config.ts
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import type { Config } from 'tailwindcss';
|
|
183
|
+
|
|
184
|
+
const config: Config = {
|
|
185
|
+
content: [
|
|
186
|
+
'./index.html',
|
|
187
|
+
'./src/**/*.{js,ts,jsx,tsx}',
|
|
188
|
+
],
|
|
189
|
+
theme: {
|
|
190
|
+
extend: {},
|
|
191
|
+
},
|
|
192
|
+
plugins: [],
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export default config;
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### prisma/schema.prisma (SQLite default)
|
|
199
|
+
|
|
200
|
+
```prisma
|
|
201
|
+
generator client {
|
|
202
|
+
provider = "prisma-client-js"
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
datasource db {
|
|
206
|
+
provider = "sqlite"
|
|
207
|
+
url = env("DATABASE_URL")
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### .env.example
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
DATABASE_URL="file:./dev.db"
|
|
215
|
+
SESSION_SECRET="change-me-in-production"
|
|
216
|
+
PORT=3001
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### vitest setup (tests/setup.ts)
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import '@testing-library/jest-dom/vitest';
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### vitest.config.ts
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { defineConfig } from 'vitest/config';
|
|
229
|
+
import react from '@vitejs/plugin-react';
|
|
230
|
+
import path from 'path';
|
|
231
|
+
|
|
232
|
+
export default defineConfig({
|
|
233
|
+
plugins: [react()],
|
|
234
|
+
test: {
|
|
235
|
+
environment: 'jsdom',
|
|
236
|
+
setupFiles: ['./tests/setup.ts'],
|
|
237
|
+
include: ['src/**/*.test.{ts,tsx}', 'server/**/*.test.ts', 'tests/unit/**/*.test.{ts,tsx}'],
|
|
238
|
+
},
|
|
239
|
+
resolve: {
|
|
240
|
+
alias: {
|
|
241
|
+
'@': path.resolve(__dirname, './src'),
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### playwright.config.ts
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
251
|
+
|
|
252
|
+
export default defineConfig({
|
|
253
|
+
testDir: './tests/e2e',
|
|
254
|
+
fullyParallel: true,
|
|
255
|
+
forbidOnly: !!process.env.CI,
|
|
256
|
+
retries: process.env.CI ? 2 : 0,
|
|
257
|
+
workers: process.env.CI ? 1 : undefined,
|
|
258
|
+
reporter: 'html',
|
|
259
|
+
use: {
|
|
260
|
+
baseURL: 'http://localhost:5173',
|
|
261
|
+
trace: 'on-first-retry',
|
|
262
|
+
},
|
|
263
|
+
projects: [
|
|
264
|
+
{
|
|
265
|
+
name: 'chromium',
|
|
266
|
+
use: { ...devices['Desktop Chrome'] },
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
webServer: {
|
|
270
|
+
command: 'npm run dev',
|
|
271
|
+
url: 'http://localhost:5173',
|
|
272
|
+
reuseExistingServer: !process.env.CI,
|
|
273
|
+
timeout: 30000,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Key Dependencies by Category
|
|
279
|
+
|
|
280
|
+
### Core (always installed)
|
|
281
|
+
- `react`, `react-dom` — React framework
|
|
282
|
+
- `typescript` — Type safety
|
|
283
|
+
- `vite`, `@vitejs/plugin-react` — Build tool and React plugin
|
|
284
|
+
|
|
285
|
+
### Styling
|
|
286
|
+
- `tailwindcss`, `postcss`, `autoprefixer` — Utility-first CSS
|
|
287
|
+
- `clsx` or `tailwind-merge` — Conditional class utilities
|
|
288
|
+
- `@radix-ui/react-*` — Headless UI primitives (if using shadcn/ui)
|
|
289
|
+
|
|
290
|
+
### Routing
|
|
291
|
+
- `react-router-dom` — Client-side routing (Vite projects)
|
|
292
|
+
- Built-in file routing (Next.js/Remix projects)
|
|
293
|
+
|
|
294
|
+
### Backend
|
|
295
|
+
- `express` — Web framework
|
|
296
|
+
- `cors` — CORS middleware
|
|
297
|
+
- `helmet` — Security headers
|
|
298
|
+
- `tsx` — TypeScript execution for Node.js
|
|
299
|
+
- `concurrently` — Run frontend and backend in parallel
|
|
300
|
+
|
|
301
|
+
### Database
|
|
302
|
+
- `prisma`, `@prisma/client` — ORM and database client
|
|
303
|
+
- Or: `drizzle-orm`, `drizzle-kit`, `better-sqlite3`
|
|
304
|
+
|
|
305
|
+
### Auth
|
|
306
|
+
- `bcrypt` or `bcryptjs` — Password hashing
|
|
307
|
+
- `express-session` — Session management
|
|
308
|
+
- `connect-sqlite3` or `connect-pg-simple` — Session storage
|
|
309
|
+
|
|
310
|
+
### Testing
|
|
311
|
+
- `vitest` — Unit test runner
|
|
312
|
+
- `@testing-library/react` — React component testing
|
|
313
|
+
- `@testing-library/jest-dom` — DOM assertions
|
|
314
|
+
- `jsdom` — DOM environment for tests
|
|
315
|
+
- `@playwright/test` — E2E testing
|
|
316
|
+
|
|
317
|
+
### Dev Tools
|
|
318
|
+
- `eslint` — Linting
|
|
319
|
+
- `@typescript-eslint/parser`, `@typescript-eslint/eslint-plugin` — TypeScript ESLint
|
|
320
|
+
- `eslint-plugin-react-hooks` — React hooks linting
|
|
321
|
+
- `eslint-plugin-react-refresh` — Fast refresh linting
|
|
322
|
+
|
|
323
|
+
## Scaffold Verification
|
|
324
|
+
|
|
325
|
+
After scaffolding, verify:
|
|
326
|
+
1. `npm run build` succeeds
|
|
327
|
+
2. `npm run typecheck` reports zero errors
|
|
328
|
+
3. `npm run lint` reports zero errors
|
|
329
|
+
4. `npm test` passes (even if there are no tests yet -- it should not error)
|
|
330
|
+
5. `npm run dev` starts both frontend and backend
|
|
331
|
+
6. Visiting `http://localhost:5173` shows the default page
|
|
332
|
+
|
|
333
|
+
## Adapting to User Choices
|
|
334
|
+
|
|
335
|
+
| User Choice | Scaffold Adjustment |
|
|
336
|
+
|-------------|-------------------|
|
|
337
|
+
| Next.js instead of Vite | Use `create-next-app` scaffold, `app/` directory, API routes instead of Express |
|
|
338
|
+
| FastAPI backend | Create `backend/` dir with Python files, `requirements.txt`, `main.py` |
|
|
339
|
+
| PostgreSQL instead of SQLite | Update `prisma/schema.prisma` datasource, add connection string to `.env.example` |
|
|
340
|
+
| No Tailwind | Skip Tailwind config, use CSS Modules pattern, add `*.module.css` examples |
|
|
341
|
+
| Zustand for state | Create `src/stores/` directory, add example store |
|
|
342
|
+
| Redux | Create `src/store/` with slices pattern, configure provider |
|
|
343
|
+
| No database | Skip Prisma setup, remove `server/db/` directory |
|
|
344
|
+
| shadcn/ui | Run `npx shadcn@latest init`, configure `components.json` |
|