RCR Backend
Supplements global typescript-guidelines skill.
Drizzle ORM
- Always use Drizzle v2 query syntax for reads:
db.query.<table>.findMany/findFirst(notdb.select().from())- Provides object-style
where, built-inwithfor relations, andcolumnsselection
- Provides object-style
- Avoid raw SQL — use query builder APIs instead of
sqltemplate literals - Mutations:
db.insert(),db.update(),db.delete() - Always upsert with
.onConflictDoUpdate()on insertions - External-source PKs:
integer('id').primaryKey()(notserial) - Never edit Drizzle meta files (
snapshot.json,_journal.json) — they're generated bydrizzle-kit
tRPC
- Routers live in
src/server/api/routers/ - Zod v4 for input validation
- Client hooks from
src/app/trpc.ts - Invalidate queries after mutations
Integrations
Canonical guide: INTEGRATIONS.md.
- Sync logic wrapped by
runIntegration; exposed viarcr sync <name> - File convention:
types.ts(Zod schemas),client.ts(API client),sync.ts(orchestration) - Respect rate limits; batch where needed; upsert for idempotency
Database Management
Canonical operations: README.md and src/server/db/db-manager.sh.
bun run db:generateto generate migration files (safe for agent)bun run db:studiofor database inspection- Never run migrations (
bun run db:migrate,bunx drizzle-kit migrate) — always provide the command for the user to run - Never run destructive operations without explicit user permission
- Backups are named by environment (
prod-{timestamp}.dump,dev-{timestamp}.dump), not database name
Agent Workflow: Media Alt Text
The rcr media commands support CLI-based alt text updates. Workflow for looped agents:
- List images needing alt text:
bash
1rcr media list --type=image --alt-text=false --limit=100 --order=recordCreatedAt - Get item with parent record context:
Returns media item plusbash1rcr media get <id> --with-recordrecord: { id, title, type, mediaCaption, url }. - Update:
bash
1rcr media update <id> '{"altText": "Description of the image"}'
Parallel processing: pre-assign media IDs per agent to avoid overlap. Parent fetches a batch, splits into chunks, each subagent processes its assigned IDs.
Schema: media table has altText (nullable), url, type, width, height, recordId (FK). ~4,090 images total.