AI-powered demand letter drafting workspace for law firms
Reducing drafting time by 50%+ through intelligent automation
# 1. Clone and install dependencies
git clone <repo-url> && cd "Demand Letter"
# 2. Start local services (PostgreSQL + Redis for future use)
docker-compose up -d
# Note: Redis is available but NOT currently used by the app
# 3. Configure environment variables
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
cp ai-service/.env.example ai-service/.env
# Edit .env files with your credentials
# 4. Run all services
# Terminal 1 - Backend
cd backend && npm install && npm run dev
# Terminal 2 - Frontend
cd frontend && npm install && npm run dev
# Terminal 3 - AI Service
cd ai-service && pip install -r requirements.txt && python lambda_handler.pyAccess: http://localhost:5173
- Problem & Solution
- Architecture Overview
- Why This Architecture?
- Tech Stack
- Key Features
- Development Guide
- Deployment
- Production Readiness
- Documentation
Personal injury attorneys spend 2.5-4.5 hours per demand letter:
- 30-60 min: Manual PDF review
- 20-40 min: Fact organization
- 60-120 min: Drafting
- 30-60 min: Review & revision
Cost: $300-600 per letter at $150/hour rates
AI-assisted 3-step workflow reduces time to 17-27 minutes (85-90% savings):
-
PDF Upload β AI Extraction (5 min)
- Upload case PDFs
- AI extracts structured facts
- Human approves/edits facts
-
Template Selection β AI Generation (2 min)
- Choose template
- AI generates complete draft
- Firm letterhead auto-applied
-
Collaborative Editing β Export (10-20 min)
- Real-time editing
- Socket.io collaboration
- Export to DOCX/PDF
ββββββββββββββββ
β Vercel β Frontend (React + TypeScript)
β (Frontend) β β’ TipTap rich text editor
ββββββββ¬ββββββββ β’ Socket.io real-time sync
β HTTPS/WSS
ββββββββΌβββββββββββββββββββββββ
β Heroku Backend (Node.js) β
β β’ Express REST API β
β β’ Socket.io WebSocket β
β β’ JWT Authentication β
β β’ DOCX/PDF Export ββββββ AWS S3
β β’ Prisma ORM β (PDF Storage)
ββββββββ¬βββββββββ¬ββββββββββββββ
β β
ββββββΌβββββ β
β Heroku β β
βPostgres β β
βββββββββββ β
β
ββββββββΌβββββββββββββββ
β Heroku AI Service β
β (Python FastAPI) β
β β’ pypdf extraction β
β β’ Anthropic API β
βββββββββββββββββββββββ
Why 3 Services?
- Frontend: User interface (Vercel for fast CDN)
- Backend: Business logic + WebSockets (Heroku for simplicity)
- AI Service: PDF + AI operations (Python ecosystem)
NOT Microservices: Just enough separation to isolate AI workload while keeping everything else together.
The Honest Answer: PDF parsing + Python ecosystem
Reality Check:
- We use
pypdf(basic text extraction, not advanced table parsing) - Anthropic SDK works in both Node.js AND Python
- Main benefit: Future ML flexibility, not current features
Could we have used Node.js? Yes! With pdf-parse + @anthropic-ai/sdk
Why we stuck with Python:
- β Slightly easier PDF parsing
- β Python ML ecosystem available for future
- β But adds complexity (separate codebase, type duplication)
File named lambda_handler.py but runs on Heroku!
Why:
- No cold starts (always-on is fine for MVP)
- Simpler deployment (git push vs Lambda packaging)
- Same platform as backend
- Predictable $5/month cost
Trade-offs:
- β No cold starts, easier deployment
- β Paying for idle time (could save $$ with Lambda at low volume)
Simple broadcast model instead of CRDT conflict resolution
Why:
- Y.js adds significant complexity
- Legal document editing is mostly sequential
- Single Heroku instance doesn't need distributed conflict resolution
- "Last write wins" is acceptable for MVP
Limitations:
- No offline editing
- No conflict resolution
- Can't scale to multiple backend instances without Redis
Decision: Skip for MVP
Why:
- Single Heroku dyno = in-memory Socket.io rooms work fine
- No session caching needed (JWT in cookies)
When to add:
- Scaling to multiple backend instances
- Need Socket.io pub/sub across servers
| Technology | Purpose |
|---|---|
| React 18 | UI framework |
| TypeScript | Type safety |
| Vite | Build tool (fast HMR) |
| TipTap | Rich text editor |
| Socket.io-client | Real-time collaboration |
| Axios | HTTP client |
| shadcn/ui + TailwindCSS | UI components |
| Technology | Purpose |
|---|---|
| Express + TypeScript | Web framework |
| Prisma | Type-safe ORM |
| Socket.io | WebSocket server |
| JWT + httpOnly cookies | Authentication |
| docx library | DOCX export |
| html-pdf-node | PDF export |
| AWS SDK | S3 integration |
| Technology | Purpose |
|---|---|
| FastAPI + Uvicorn | Async web framework |
| pypdf | PDF text extraction |
| Anthropic SDK | Claude API |
| Pydantic | Request validation |
| Service | Platform | Cost/Month |
|---|---|---|
| Frontend | Vercel Hobby | $0 |
| Backend | Heroku Eco | $5 |
| AI Service | Heroku Eco | $5 |
| Database | Heroku Postgres | $5 |
| Storage | AWS S3 | ~$2 |
| AI API | Anthropic | $10-50 |
| Total | $27-67/month |
- Direct upload to S3 (presigned URLs)
- pypdf text extraction
- Stores metadata in PostgreSQL
- Claude Haiku 4.5 for cost efficiency ($0.25/M tokens)
- Structured JSON output (parties, dates, injuries, damages)
- Citations with PDF filename + page reference
- Review UI for fact approval
- Edit fact text inline
- Only approved facts used in generation
- Firm-specific templates
- Variable substitution
- Reusable paragraph modules
- Single-stage prompt with approved facts
- Firm letterhead automatically applied
- HTML output for rich formatting
- Socket.io WebSocket connections
- Live presence indicators
- Broadcast model (last write wins)
- Auto-save every 5 seconds
- DOCX: Uses
docxlibrary, HTMLβDOCX conversion - PDF: Uses
html-pdf-node+ Puppeteer - Firm letterhead included
- Professional formatting (Times New Roman, 1" margins)
- Snapshot-based versioning
- Full document snapshots on each save
- Restore to any previous version
- Node.js 18+
- Python 3.11+
- PostgreSQL 15+
- Docker Desktop (for local services)
demand-letter/
βββ frontend/ # React + TypeScript
βββ backend/ # Node.js + Express
βββ ai-service/ # Python FastAPI
βββ docker-compose.yml
βββ README.md
Backend (backend/.env):
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/demand_letters
JWT_SECRET=your-secret-key
JWT_REFRESH_SECRET=your-refresh-secret
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
S3_BUCKET_NAME=your-bucket
AI_SERVICE_URL=http://localhost:8000
CORS_ORIGIN=http://localhost:5173Frontend (frontend/.env):
VITE_API_URL=http://localhost:3000AI Service (ai-service/.env):
ANTHROPIC_API_KEY=sk-ant-your-key
ANTHROPIC_MODEL=claude-haiku-4-5-20251001cd backend
npx prisma migrate dev # Run migrations
npx prisma studio # Open database GUI
npx prisma generate # Regenerate Prisma client# Backend hot reload (nodemon)
cd backend && npm run dev
# Frontend hot reload (Vite HMR)
cd frontend && npm run dev
# AI service hot reload (uvicorn --reload)
cd ai-service && python lambda_handler.pyBackend:
heroku create steno-backend
heroku addons:create heroku-postgresql:essential-0
heroku config:set JWT_SECRET=... AWS_ACCESS_KEY_ID=...
git subtree push --prefix backend heroku mainAI Service:
heroku create steno-ai-service
heroku config:set ANTHROPIC_API_KEY=...
git subtree push --prefix ai-service heroku mainFrontend: Deploy to Vercel
cd frontend
vercel --prodSee HEROKU_DEPLOYMENT.md for detailed steps.
This is an MVP designed for rapid development. For production, see PRODUCTION_READINESS.md for detailed improvements needed:
- β Single Heroku instance (no load balancing)
- β No Redis (Socket.io won't scale to multiple instances)
- β Simple broadcast (no conflict resolution)
- β No rate limiting
- β Minimal error handling
- β No automated tests
- β No monitoring/alerting
- β Secrets in .env files
Security (High Priority):
- Rate limiting (express-rate-limit)
- Input sanitization
- CORS whitelist
- Secrets management (AWS Secrets Manager)
- File upload validation (magic bytes)
Scalability (Medium Priority):
- Redis pub/sub for multi-instance Socket.io
- Y.js CRDT for conflict resolution
- Database connection pooling
- Lambda migration for AI service (cost optimization)
Observability (High Priority):
- Structured logging (JSON format)
- APM (New Relic, Datadog)
- Error tracking (Sentry)
- Metrics dashboards
Testing (High Priority):
- Unit tests (Jest)
- Integration tests (Supertest)
- E2E tests (Playwright)
See PRODUCTION_READINESS.md for complete roadmap.
- ARCHITECTURE.md - Detailed architecture, data flows, design decisions
- PRODUCTION_READINESS.md - Production improvement roadmap
- HEROKU_DEPLOYMENT.md - Deployment guide
- memory-bank/ - Project context and progress
Comprehensive JSDoc comments added to key services (760+ lines):
backend/src/services/ExportService.ts- DOCX/PDF export with HTML conversion, production TODOsbackend/src/services/FactService.ts- Fact extraction, approval workflow, draft generation orchestrationfrontend/src/utils/textConverter.ts- HTML/text format conversion utilitiesbackend/src/controllers/exportController.ts- Export endpoint handlers
All methods include: purpose, parameters, return types, flow explanations, and production considerations.
Proprietary - Steno Β© 2025
- Read project context in
memory-bank/projectbrief.md - Check
memory-bank/activeContext.mdfor current focus - Review code standards in
ARCHITECTURE.md - Create feature branch:
git checkout -b feature/your-feature - Run linters before committing
Project Status: MVP Complete, Interview Prep
Last Updated: January 2025
User β Frontend β Backend β S3 (PDF)
β
AI Service β S3 (download)
β (pypdf extraction)
Anthropic API
β (facts JSON)
Backend β Database
β (user approves)
AI Service β Anthropic
β (HTML draft)
Backend β Database
β
Frontend (TipTap editor)
- Backend API:
backend/src/index.ts- Express app setup - Document Service:
backend/src/services/DocumentService.ts- CRUD + S3 - Fact Extraction:
backend/src/services/FactService.ts- AI orchestration - Export:
backend/src/services/ExportService.ts- DOCX/PDF generation - WebSocket:
backend/src/services/SocketService.ts- Socket.io rooms - AI Entry:
ai-service/lambda_handler.py- FastAPI app - PDF Parsing:
ai-service/src/services/pdf_extractor.py- pypdf - AI Calls:
ai-service/src/services/anthropic_service.py- Claude API
users β documents β pdfs β facts
β
collaborators
β
versions
Login β bcrypt verify β JWT (15min) + Refresh (7d)
β
httpOnly cookies
β
Middleware verifies on each request
This architecture demonstrates pragmatic engineering: Right-sized for the problem, simple where possible, complex only where necessary.