SMS-to-PDF
Turn Text Messages into Professional PDFs
Built as a production reference for AI-powered document pipelines — three microservices, structured AI extraction, and full observability.
The Problem
Creating professional documents — invoices, agreements, receipts — takes more steps than it should. Open an app, fill out a form, double-check the numbers, export the PDF, email it to the client. For freelancers and small teams who send the same types of documents over and over, those minutes add up to hours every week. The process should be as simple as describing what you need.
The Solution
SMS-to-PDF lets you create professional documents by sending a single text message. You text something like:
“invoice for John Doe, john@example.com, 3 hours consulting at $150/hr, due March 15”
Seconds later, a polished PDF lands in your inbox — formatted, calculated, and ready to forward to your client. No apps to open, no forms to fill out, no manual formatting.
Users sign up, upload their own Word templates with {{placeholder}} fields, buy a credit pack, and every document they generate costs a single credit. The system ships with invoices and agreements out of the box, but you can add any document type — receipts, work orders, contracts — by uploading a .docx file.
Under the Hood
The system is split into three independent microservices communicating through Redis queues:
SMS → Twilio webhook → FastAPI (main app)
→ Match template (system or user-uploaded)
→ Claude API extracts fields as structured JSON (tool_use)
→ Validate required fields
→ Enqueue render job → Redis queue
↓
Renderer sidecar
→ Fill .docx template (docxtpl) → LibreOffice headless → PDF
→ Enqueue email job → Redis queue
↓
Emailer sidecar
→ SendGrid delivers PDF attachment
→ SSE event published back to UI
The live demo on the landing page shows all five pipeline steps lighting up in real-time as the message is processed:
- Message Received — The raw SMS or demo message hits the FastAPI server
- Template Matched — Keyword matching identifies the document type from both system and user-uploaded templates
- Fields Extracted — Claude AI parses the message into structured JSON using
tool_use, including typo correction for misspellings and capitalization - Validation Passed — Required fields are checked; missing data triggers an SMS reply asking to resend
- PDF Rendered — The renderer sidecar fills the Word template and converts to PDF via LibreOffice headless
SaaS Platform
Phone OTP Authentication
Users sign in with their phone number via Twilio Verify. A 6-digit code is sent by SMS, verified on the server, and exchanged for a JWT access token (15 min) plus a refresh token (7 days). All dashboard API calls are authenticated via Authorization: Bearer headers.
Dashboard & Word Templates
The dashboard gives each user a private workspace to manage templates, view generated documents, purchase credits, and configure delivery settings.
Adding a new document type means uploading a .docx file with {{variable}} placeholders. The system auto-detects the field names from the template, and Claude uses them as the extraction schema. No code, no configuration — just a Word document.
Credit-Based Billing
Each PDF generation costs one credit. Users purchase credit packs ($5 for 20, $10 for 50, $35 for 200) through a checkout flow. Every transaction is logged — purchases, deductions, and balances are all visible in the dashboard.
Key Technical Decisions
Claude tool_use for Structured Extraction
The critical insight: Claude’s tool_use feature forces output to match a JSON schema. Each template’s field definitions become the tool’s input_schema at runtime. The AI returns validated, structured data — or the system asks for clarification. It never generates a document from bad data.
Word Templates + LibreOffice Headless
The original system used HTML templates with WeasyPrint. The new architecture uses .docx templates rendered with docxtpl and converted to PDF via LibreOffice’s headless mode. This lets users design templates in Word — a tool they already know — with full control over fonts, layout, and branding, without writing any code.
Microservices via Redis Queues
The monolithic pipeline was decomposed into three services:
- Main app — handles SMS reception, template matching, field extraction, and enqueues render jobs
- Renderer sidecar — consumes from
render_queue, fills Word templates, converts to PDF, enqueues email jobs - Emailer sidecar — consumes from
email_queue, sends PDF via SendGrid, publishes SSE events
Each service is independently deployable and scalable. Redis BRPOP provides reliable at-least-once delivery between services.
PostgreSQL + Async SQLAlchemy
The SaaS layer uses PostgreSQL with async SQLAlchemy for users, templates, documents, credit transactions, and waitlist leads. Alembic handles schema migrations. The database supports soft-delete on templates and full audit trails on billing.
Production Observability
Prometheus metrics ship out of the box: request rates by source (demo vs. webhook), processing duration histograms (p50/p95/p99), document counts by template type, and error breakdowns. A pre-configured Grafana dashboard is included in the Docker Compose stack.

Architecture
| Component | Technology |
|---|---|
| Main App | Python + FastAPI |
| Renderer | docxtpl + LibreOffice headless |
| Emailer | SendGrid (PDF attachments) |
| Auth | Twilio Verify (OTP) + JWT |
| Database | PostgreSQL + async SQLAlchemy + Alembic |
| AI Extraction | Claude API (tool_use) |
| Queues | Redis (BRPOP + pub/sub) |
| Real-Time UI | Server-Sent Events (SSE) |
| Monitoring | Prometheus + Grafana |
| Hosting | Docker Compose, DigitalOcean |
Results
- < 3 seconds end-to-end from SMS to PDF in inbox
- Microservices architecture — app, renderer, and emailer as independent workers
- Word template uploads — users design documents in a tool they already know
- Credit-based billing with full transaction audit trail
- Phone OTP authentication via Twilio Verify + JWT
- Real-time pipeline visualization via SSE in the live demo
- Full observability with Prometheus metrics and Grafana dashboards
- Single
docker compose upto run the entire stack
Tech Stack
| Layer | Stack |
|---|---|
| API | FastAPI, Uvicorn, Pydantic |
| Auth | Twilio Verify, python-jose (JWT) |
| AI | Claude API (Anthropic SDK, tool_use) |
| Database | PostgreSQL, async SQLAlchemy, Alembic |
| Templates | docxtpl (Word), LibreOffice headless (PDF) |
| Messaging | Twilio (SMS in/out), SendGrid (email) |
| Queues & Streaming | Redis BRPOP + pub/sub + SSE |
| Monitoring | Prometheus, Grafana, structlog |
| Infrastructure | Docker Compose, DigitalOcean |