This is a plain-language blueprint of how Wraft works — for developers and for anyone curious about the system. Read top to bottom; each drawing explains one idea.
Today a single contract lives in four different places. Its data is trapped inside a flat file, unstructured, and impossible to automate.
A contract starts in Google Docs (authoring), gets signed in DocuSign, is stored in Drive, and its metadata is — nowhere. Four tools hold four copies. Change the layout and the data breaks. Rebrand and every old file still looks old. Want to generate 500 invoices straight from a database? You can't.
Wraft splits a document into its three real ingredients — data, layout, and theme — then compiles them back together. Change one without breaking the others.
Think of Wraft as “Git + Figma + DocuSign for documents, but API-first and structured.” You don't hand-write a finished document. You define what a kind of document is, fill in the blanks with real data, and the machine produces a perfect, branded result every time.
Like parts in an assembly drawing, each component has one job. Bolt them together and you get a complete, compliant document.
Defines a type of document, like a database schema. An “Offer Letter” variant has fields such as candidate_name, salary, joining_date. It enforces what content a document may hold.
An actual instantiation of a Variant. It holds the real values for those fields — no styling baked into the data payload at all.
Determines how data is arranged on a page. Wraft drives layout engines like Typst and LaTeX — controlling paragraphs, sections, tables, and spacing.
The visual identity applied globally or per-document: typography, color palettes, header styles. Ensures brand consistency without manual tweaking.
Defines state transitions that mirror real-world approval steps: Draft → Review → Approved → Signed → Archived. Automates a document through its full lifecycle.
ContentType schema; a Document is an Instance. Each ContentType belongs_to a Layout, a Theme, and a Flow, and has_many Instances.Wraft behaves like a compiler. Raw structured data goes in one end, passes through transformation stages, and a polished PDF comes out the other.
① Structured input (JSON) — the document instance begins as a JSON payload conforming to its Variant schema. No styling yet. ② AST / Markdown conversion — the JSON is mapped into a text-friendly intermediate form. ③ Layout + theme — the intermediate structure is processed by the layout engine (Typst) and injected with the theme's visual properties. ④ Compilation — the layout files are rendered into the final output format. ⑤ Output — a consistent, branded PDF, ready for signing.
LogicPipeline and Pipelines; final rendering goes through DocConversion and the registered engines. Assets are saved to MinIO via Waffle.Wraft documents are stateful. They model the real-world progression of paperwork — from a rough draft to a signed, archived record.
Defining document variants (schemas), writing content, connecting layout and design to raw data, and collaborating on the structured data payload.
Ensuring correctness and compliance. Custom workflows set up conditional review cycles; role-based validation restricts approval to specific teams or roles.
The final, legally binding step: trusted digital signature integrations, with immutable versions and audit trails for compliance.
Archival and retrieval in a centralized, secure repository — with queryable metadata that enables search, automation, and AI processing later.
Three parts work together: a Next.js frontend, a Phoenix/Elixir API, and a set of infrastructure services. The frontend never touches the database directly — everything goes through the API.
A Next.js 15 monorepo (Turborepo + pnpm). The main app is apps/web; shared building blocks live in packages: @wraft/ui (Base UI + Tailwind), @wraft/icon, editor, and a typst package. Server Components by default; Client Components only when interactivity is needed.
An Elixir/Phoenix API organized into contexts in lib/wraft_doc/. Auth is JWT via Guardian; file uploads go through Waffle to MinIO; background work runs on Oban; collaborative editing uses Yjs (CRDTs). Everything is API-first.
PostgreSQL 16 holds all structured data. MinIO (S3-compatible) stores files and generated documents. Oban runs build jobs and background tasks. Typesense powers search over the document repository. A separate website/ Astro project serves the public landing page.
From the moment data enters to the moment a document is filed away, it follows one path. Inputs are collected, processed, generated, and stored.
Data arrives from forms, CSV, Shopify, or Google Sheets (① input). It is validated and routed through the logic pipeline (② process). The pipeline hands it to the generation engines, which compile it against a layout and theme into a PDF (③ generate). The finished document and its metadata are saved to the MinIO repository, where they become searchable and ready for automation (④ store).
Wraft is built API-first. Every action available in the interface can be triggered programmatically — making it a powerful engine for automation, not just an editor.
Sales teams fill structured fields (pricing, client, deliverables) via a form or CRM integration, and Wraft compiles a perfectly branded proposal PDF — instantly.
Draft from predefined variants, pass through custom review states, sign with digital signature providers, and archive — all triggerable by external systems.
A pipeline that turns raw backend data into compliant, styled PDFs — ideal for invoices, receipts, and reports generated with zero human intervention.
Integrated digital signing workflows produce legally binding agreements, with the signed artifact and its metadata stored centrally in the repository.
A quick-reference bill of materials. Every component the machine is built from, grouped by where it lives.
| Layer | Technology | Role |
|---|---|---|
| Backend | Phoenix 1.7 · Elixir 1.14 · Erlang 26 | API server, contexts, WebSocket channels |
| ORM / DB | Ecto · PostgreSQL 16 | Structured data, schemas, migrations |
| Auth | Guardian (JWT) | Token authentication, flexible pipelines |
| File uploads | Waffle | Uploads to S3 / MinIO |
| Object storage | MinIO (S3-compatible) | Documents, assets, generated PDFs |
| Background jobs | Oban | Builds, imports, scheduled work |
| Search | Typesense (ExTypesense) | Full-text search over repository |
| Collab editing | Yjs · y_ex (CRDT) | Real-time collaborative document editing |
| Layout engine | Typst · LaTeX | Document structure & rendering |
| AI | Jido · instructor_ex | LLM agents, extraction, suggestions |
| API spec | OpenApiSpex · Swagger UI | API documentation at /spec |
| Frontend | Next.js 15 · React 19 · App Router | Main web application |
| UI | Base UI · Tailwind CSS · CVA | Headless components + tokens (@wraft/ui) |
| Monorepo | Turborepo · pnpm workspaces | apps/ + packages/ structure |
| Website | Astro | Public landing page |
localhost:4000 (mix phx.server), frontend on localhost:3000 (pnpm dev), MinIO console on :9001. API spec & Swagger at /spec/openapi and /spec/swaggerui.