13 KiB
Real Backend Architecture Decision
Status: Proposed decision
Date: 2026-06-06
Scope: Move ProjectBrain from Vite mock middleware to a real backend architecture without implementing that backend yet.
Decision
ProjectBrain should move to a dedicated TypeScript backend using Fastify, PostgreSQL, Prisma, Zod, and a background worker backed by Redis/BullMQ. The current Vite middleware should remain as a dev/demo contract surface until the frontend is switched behind a configuration flag.
This keeps the product API-first, self-hostable, Docker-friendly, and aligned with the existing TypeScript contract layer while leaving room for later AI-assisted imports, codebase analysis jobs, file uploads, MCP integration, and ChatGPT/custom app connectors.
Current Backend-Mock State
The current backend surface is implemented as Vite dev middleware in src/shared/api/b1ReadBackend.ts and mounted from vite.config.ts under /api/*.
B1-B6 endpoint families now covered as mock contract surface:
- B1: Projects, Workspace, DNA, context-pack summary.
- B2: Feature groups, Features, Evidence reads.
- B3: Context Packs and prompt generation mock.
- B4: Checks and review-board mutations.
- B5: Builds, Regressions, Snapshots.
- B6: Insights, Relationships, Knowledge, Memory Rules.
Current mock limitations:
- In-memory state only; data resets when the Vite process restarts.
- No database, migrations, transactions, row-level integrity, or durable idempotency store.
- No auth, permissions, tenancy, or user ownership model.
- No real AI calls; prompt/current-state style operations are deterministic mock outputs.
- No file upload storage, parsing pipeline, codebase scan worker, or long-running job runner.
- Vite middleware is development infrastructure, not a production backend boundary.
- Idempotency is process-local and keyed by method, path, and
Idempotency-Key.
Where state lives today:
src/shared/lib/mock-data.ts: central fixtures used by the UI and mock clients.src/shared/api/mockClient.ts: frontend in-memory store used byprojectBrainClient.src/shared/api/b1ReadBackend.ts: separate Vite middleware in-memory state seeded from mock data.
Contracts and docs currently present:
docs/API_CONTRACT_PREP.mddocs/BACKEND_B1_READ_API.mddocs/BACKEND_B2_FEATURES_EVIDENCE_READ_API.mddocs/BACKEND_B3_CONTEXT_PACKS_PROMPTS_API.mddocs/BACKEND_B4_CHECKS_REVIEW_API.mddocs/BACKEND_B5_BUILDS_REGRESSIONS_SNAPSHOTS_API.mddocs/BACKEND_B6_INSIGHTS_RELATIONSHIPS_KNOWLEDGE_MEMORY_API.mdsrc/shared/api/types.tssrc/shared/api/contracts.tssrc/shared/api/projectBrainClient.ts
Frontend consumption today:
- UI pages should consume through
projectBrainClientor higher-level selectors/actions. projectBrainClientcurrently delegates tomockClient.- The Vite middleware is not yet the frontend source of truth.
- Future switching should happen inside the client boundary, not by changing pages directly.
Backend Options
A) Node/Fastify Backend
Pros:
- Best fit with the existing TypeScript contracts and model types.
- Shared Zod schemas can validate both API requests and frontend clients.
- Fastify has strong performance, structured plugins, JSON schema support, and good Docker ergonomics.
- Natural fit for API-first design, MCP servers, ChatGPT app connectors, and local self-hosting.
- Background jobs can use BullMQ/Redis with a separate worker process.
- File upload/import endpoints can stream to local disk or S3-compatible storage.
Cons:
- Codebase analysis and ML-heavy pipelines may eventually want Python helpers.
- Requires discipline around service/repository boundaries to avoid a large Node monolith.
- Worker deployment adds another runtime process.
Migration effort:
- Moderate. Existing TypeScript DTOs, contract docs, and mock behavior can be ported incrementally.
Fit:
- AI/codebase analysis later: good for orchestration; Python sidecars can be added for specialist analysis.
- File uploads/imports later: good.
- Self-hosting: excellent.
- Docker deployment: excellent.
- Future MCP/ChatGPT connector/API: excellent.
B) FastAPI Backend
Pros:
- Excellent for Python-native AI/code analysis, embeddings, parsing, and background processing.
- Strong OpenAPI generation and Pydantic validation.
- Good for future ML-heavy worker code.
Cons:
- Introduces a second primary language while the app contracts are already TypeScript.
- DTO drift risk between frontend TypeScript and backend Python models.
- More migration work to preserve existing TypeScript contract shape.
- Frontend and backend type sharing becomes generated rather than native.
Migration effort:
- Moderate to high. Requires translating contracts into Pydantic or generating schemas carefully.
Fit:
- AI/codebase analysis later: excellent.
- File uploads/imports later: excellent.
- Self-hosting: good.
- Docker deployment: good.
- Future MCP/ChatGPT connector/API: good, but TypeScript app connector work may be less direct.
C) Next.js-Style Fullstack
Pros:
- Single deployment surface if the product were already Next.js.
- API routes and UI can live together.
Cons:
- Not applicable without migrating the existing Vite SPA.
- Would create a framework migration before the backend architecture is settled.
- Long-running imports and codebase analysis jobs still need separate worker infrastructure.
Migration effort:
- High and not justified now.
Fit:
- AI/codebase analysis later: mixed.
- File uploads/imports later: good with extra worker setup.
- Self-hosting: good.
- Docker deployment: good.
- Future MCP/ChatGPT connector/API: good, but not worth the app migration cost.
D) Keep Vite Middleware Only
Pros:
- Lowest immediate effort.
- Good demo and contract-testing surface.
- Useful during frontend prototyping.
Cons:
- Not a production backend.
- No durable persistence, job runner, upload pipeline, auth boundary, or deployment separation.
- Dev server lifecycle makes idempotency and state unreliable.
- Encourages backend growth inside frontend tooling.
Migration effort:
- None short-term, but high long-term cleanup cost if it keeps expanding.
Fit:
- AI/codebase analysis later: poor.
- File uploads/imports later: poor.
- Self-hosting: poor for production.
- Docker deployment: demo only.
- Future MCP/ChatGPT connector/API: poor as a durable API target.
Recommended Architecture
Use a dedicated Fastify backend in TypeScript.
Recommended stack:
- Runtime/framework: Node.js with Fastify.
- Database: PostgreSQL.
- ORM/query layer: Prisma initially, with raw SQL escape hatches for graph/query-heavy paths.
- Validation/schema: Zod as source-level request/response validation, optionally exported to OpenAPI.
- Background jobs: BullMQ with Redis, split into
apiandworkerprocesses. - File storage: local filesystem volume for self-hosting first, with S3-compatible adapter later.
- API structure: versioned REST under
/api/v1, preserving current envelopes. - Logging: Pino structured logs with request IDs.
- Error handling: centralized Fastify error handler returning the existing error envelope.
- Config/env:
.envfor local,.env.example, environment-specific Docker Compose values. - Docker:
frontend,api,worker,postgres,redis, and optionalstoragevolume.
Why this choice:
- Keeps TypeScript contracts close to the frontend.
- Avoids a framework migration.
- Supports self-hosting and Docker from the beginning.
- Leaves room for Python analysis workers later without making Python the main API boundary.
- Fits future MCP/ChatGPT/custom app API use because the backend becomes a stable HTTP service.
Proposed Folder Structure
apps/
web/
# current Vite React app, moved later or referenced in place
api/
src/
server.ts
app.ts
config/
plugins/
routes/
v1/
projects.routes.ts
workspace.routes.ts
features.routes.ts
context-packs.routes.ts
checks.routes.ts
builds.routes.ts
knowledge.routes.ts
services/
repositories/
schemas/
errors/
idempotency/
logging/
worker/
src/
worker.ts
jobs/
processors/
packages/
contracts/
src/
api-types.ts
schemas.ts
envelopes.ts
This repo does not need to be reorganized immediately. R1 can start with a smaller backend/ folder if a monorepo move is too disruptive.
API Versioning
- New backend routes should use
/api/v1. - Current Vite middleware may remain under
/apifor dev/demo until switch-over. - Response envelope remains:
{ "data": {}, "meta": { "requestId": "...", "timestamp": "..." } }
- Error envelope remains:
{ "error": { "code": "...", "message": "...", "validation": [] }, "meta": { "requestId": "...", "timestamp": "..." } }
- Idempotency remains required for write endpoints using
Idempotency-Key, but should move to a durable table:- method
- path
- key
- request hash
- response body
- status code
- expiresAt
Migration Strategy
R1: Real backend skeleton
- Add Fastify API skeleton.
- Add health endpoint.
- Add shared envelope helpers.
- Add request ID middleware.
- Add config/env validation.
- Add Docker Compose with Postgres and Redis.
- Do not switch frontend yet.
R2: Projects / Workspace / DNA reads
- Implement B1 against database-backed repositories.
- Seed database from
mock-data.ts. - Keep Vite middleware as fallback/demo.
R3: Features / Evidence reads
- Implement B2.
- Add feature/evidence schema migrations.
- Preserve pagination and filter response shape.
R4: Context Packs / Prompts mock generation
- Implement context-pack reads/writes.
- Keep prompt generation deterministic mock-only.
- Store generated prompt records in the database.
R5: Checks / Review mutations
- Implement checks, review board grouping, review actions, conversions.
- Add durable idempotency.
R6: Builds / Regressions / Snapshots
- Implement build journal, regression memory, snapshot compare.
- Keep compare deterministic until richer diffing exists.
R7: Knowledge / Memory / Relationships / Insights
- Implement B6 endpoints against the database.
- Preserve include-in-context-pack behavior.
- Add relationship integrity checks.
R8: Frontend API switch
- Update
projectBrainClientto choose real HTTP client ormockClientvia config flag. - Pages must continue to use
projectBrainClient, selectors, and actions only. - No page-level direct fetch calls.
R9: Persistence hardening
- Add migrations, seed scripts, backup/restore guidance, indexes, idempotency TTL cleanup, and integration tests.
R10: Import/codebase analysis jobs
- Add upload endpoints and job creation.
- Add worker processors for ZIP/codebase/document analysis.
- Add optional Python sidecar only for analysis tasks that genuinely need Python libraries.
Source of Truth Transition
mock-data.tsremains a fixture and demo seed source.- The real PostgreSQL database becomes source of truth after R8/R9.
- Seed scripts should transform fixture data into database rows.
- Migration scripts should be repeatable for local self-hosting.
- The frontend must keep using
projectBrainClient; switching source should be a client configuration concern. - Vite middleware should be retired only after the real backend covers B1-B6 and the frontend switch is stable.
Docker / Self-Hosting Notes
Recommended services:
web: Vite-built static frontend served by Nginx or a small Node static server.api: Fastify HTTP API.worker: BullMQ worker for imports and analysis.postgres: ProjectBrain database.redis: queue and job coordination.storage: mounted local volume for uploads and generated artifacts.
Self-hosting defaults:
- No paid API required for core CRUD/project memory.
- AI providers configured through optional environment variables later.
- Local file storage first, S3-compatible storage optional.
- Health checks for
web,api,worker,postgres, andredis.
Alternatives Rejected
- FastAPI as primary API: strong for analysis, but higher contract drift risk and more translation work from existing TypeScript contracts.
- Next.js fullstack: would require a frontend framework migration before backend needs justify it.
- Vite middleware as production backend: useful contract scaffold, but not durable or deployable as the product backend.
Open Questions
- Should the repo become a formal monorepo now, or should R1 start with a
backend/folder? - Should Prisma be the long-term ORM, or should graph-heavy relationship queries move to Kysely/raw SQL later?
- Should file storage stay local-only for v1 self-hosting, or ship an S3-compatible adapter in the first backend release?
- What auth model is desired later: local admin, single-user self-hosted, or multi-user teams?
- Should Python analysis workers be planned from R10 or deferred until codebase import requirements are precise?
Final Recommendation
Proceed with R1 as a dedicated Fastify backend skeleton, keeping the Vite middleware untouched as a contract/demo reference. Do not add B7 to the middleware. The next implementation phase should create the real backend foundation and implement only health/config/envelope plumbing before porting B1.