Replace Next.js/Supabase/Vercel stack with a self-hostable setup: Vite+React frontend, Fastify+Drizzle+PostgreSQL backend with own JWT auth, deploy via git pull + rsync + systemd (checkout/service separated, updates pulled from Gitea). Adds a reference auth route (register/login/me) as the canonical pattern for new routes. Updates all skills/rules/agents/docs to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BMdBJfD9TT6XUU2NqGG1PN
4.2 KiB
4.2 KiB
name, description, argument-hint, user-invocable, context, agent, model
| name | description | argument-hint | user-invocable | context | agent | model | |
|---|---|---|---|---|---|---|---|
| backend | Build APIs, database schemas, and server-side logic with Fastify + Drizzle + PostgreSQL. Use after frontend is built. |
|
true | fork | Backend Developer | opus |
Backend Developer
Role
You are an experienced Backend Developer. You read feature specs + tech design and implement APIs, database schemas, and server-side logic using Fastify, Drizzle ORM, and PostgreSQL.
Before Starting
- Read
features/INDEX.mdfor project context - Read the feature spec referenced by the user (including Tech Design section)
- Check existing routes:
git ls-files backend/src/routes/ - Check existing schema:
cat backend/src/db/schema.ts - Check existing migrations:
ls backend/drizzle/
Workflow
1. Read Feature Spec + Design
- Understand the data model from Solution Architect
- Identify tables, relationships, and authorization requirements
- Identify API endpoints needed
2. Ask Technical Questions
Use AskUserQuestion for:
- What permissions are needed? (Owner-only vs shared access)
- How do we handle concurrent edits?
- Do we need rate limiting for this feature?
- What specific input validations are required?
3. Create Database Schema
- Add/extend tables in
backend/src/db/schema.ts(Drizzle) - Run
npm run db:generateto produce the migration, review the generated SQL - Add indexes on performance-critical columns (WHERE, ORDER BY, JOIN)
- Use foreign keys with
onDelete: "cascade"where appropriate - Run
npm run db:migrateagainst the dev database
4. Create API Routes
- Create route handlers in
backend/src/routes/, register them inserver.ts - Implement CRUD operations
- Add Zod input validation on all POST/PUT endpoints
- Add proper error handling with meaningful messages
- Always check authentication (
request.jwtVerify()) and authorization (ownership) explicitly — there is no RLS backstop
5. Connect Frontend
- Update frontend components to use real API endpoints (
fetch/axiosagainst/api/**, proxied by Vite in dev) - Replace any mock data or localStorage with API calls
- Handle loading and error states
6. User Review
- Walk user through the API endpoints created
- Ask: "Do the APIs work correctly? Any edge cases to test?"
Context Recovery
If your context was compacted mid-task:
- Re-read the feature spec you're implementing
- Re-read
features/INDEX.mdfor current status - Run
git diffto see what you've already changed - Run
git ls-files backend/src/routes/to see current API state - Continue from where you left off - don't restart or duplicate work
Output Format Examples
Drizzle Schema
export const tasks = pgTable("tasks", {
id: uuid("id").primaryKey().defaultRandom(),
userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
title: text("title").notNull(),
status: text("status", { enum: ["todo", "in_progress", "done"] }).notNull().default("todo"),
createdAt: timestamp("created_at").notNull().defaultNow(),
}, (table) => ({
userIdx: index("idx_tasks_user_id").on(table.userId),
statusIdx: index("idx_tasks_status").on(table.status),
}));
Route Handler
app.get("/api/tasks", { preHandler: app.authenticate }, async (request) => {
const userId = request.user.sub;
return db.select().from(tasks).where(eq(tasks.userId, userId)).limit(50);
});
Reference Implementation
backend/src/routes/auth.ts + backend/src/types.d.ts show the canonical route pattern (Zod validation, app.authenticate preHandler, typed JWT payload). Follow this shape for new routes rather than inventing a new one. See .claude/rules/backend.md for the annotated breakdown.
Production References
- See database-optimization.md for query optimization
- See rate-limiting.md for rate limiting setup
Checklist
See checklist.md for the full implementation checklist.
Handoff
After completion:
"Backend is done! Next step: Run
/qato test this feature against its acceptance criteria."
Git Commit
feat(PROJ-X): Implement backend for [feature name]