- Editor frontend
- Vite + React 18 application built around an in-house Plate.js editor. We pulled the relevant portions of Plate into our codebase via a registry pattern so the editor has zero hidden runtime dependencies. Streaming AI uses Vercel AI SDK on the client side, wired to the AI service over Server-Sent Events.
- AI service
- Python service that owns retrieval, embedding, and the orchestration of Claude calls. Why a separate service rather than running everything from the Next-adjacent stack: retrieval is CPU-heavy and memory-resident, and we wanted to scale it independently of the editor. The Python service exposes a small typed HTTP surface; Claude is the underlying LLM.
- Document service
- Next.js (separately deployable) handles document storage, parsing, versioning, and the DOCX export pipeline. It exposes a typed API consumed by both the editor and any future client. Parsing uses tuned PDF extractors per document class; export uses `@platejs/docx-io` with custom serializers.
- Proposal-creator service
- A fourth small service handles bulk document generation — populating a templated DOCX with project metadata, signatures, header logos. Triggered at the end of the proposal lifecycle, kept separate so its templates can evolve without redeploying the editor.
- Data layer
- Postgres with Drizzle for the document service. Embeddings stored alongside source-document metadata; the AI service hits the same database in read-only mode for retrieval. Section-level versioning is modeled as an append-only history table.
- Monorepo + infra
- Turborepo with pnpm. Four apps (editor, AI service, document service, proposal-creator), shared packages for the editor primitives, the DOCX exporter, and the typed API contracts. Each app deploys independently — Vercel for the Next pieces, a container runtime for the Python AI service.