Production-grade PWA for converting scanned PDFs into editable vector PDFs and AI-powered fillable forms.
VectorForge PDF is a full-stack monorepo that transforms scanned, raster PDFs into fully editable, searchable vector PDFs — and generates interactive fillable forms using AI. It ships as a Progressive Web App with offline support, cloud storage integrations, an MCP server, and automation hooks for n8n and Make.com.
| Feature | Details |
|---|---|
| OCR | Tesseract.js, Google Cloud Vision, AWS Textract (switchable via env var) |
| Font Matching | 54-entry Google Fonts catalog, rule-based + confidence scoring, automatic download & caching |
| Vectorization | Potrace for line art & graphics, JPEG encoding for photos, Hough transform for charts |
| PDF Reconstruction | pdf-lib page rebuild with embedded fonts, pixel-level validation via pixelmatch |
| AI Fillable Forms | Claude API field detection → AcroForm generation (text, checkbox, radio, select, signature) |
| Cloud Connectors | Google Drive, Dropbox, Notion, OneDrive — OAuth 2.0 with encrypted token storage |
| PWA | Service worker, Web App Manifest, IndexedDB, Background Sync, Web Push (VAPID) |
| Automation | n8n community node, Make.com app, webhook dispatch with HMAC-SHA256 signing |
| MCP Server | 7 tools + SSE transport for Claude Desktop and agent integrations |
vectorforge-pdf/
├── apps/
│ ├── api/ # Node.js + Express REST API (port 4000)
│ │ ├── prisma/ # PostgreSQL schema (9 models)
│ │ └── src/
│ │ ├── services/
│ │ │ ├── ocr/ # Tesseract · Google Vision · AWS Textract
│ │ │ ├── vectorize/# Potrace-based raster→vector pipeline
│ │ │ ├── fonts/ # Google Fonts matcher & downloader
│ │ │ ├── pdf/ # Reconstruct + pixelmatch validation
│ │ │ ├── fields/ # Claude AI field detection & AcroForm gen
│ │ │ └── connectors/ # GDrive · Dropbox · Notion · OneDrive
│ │ ├── queue/ # BullMQ workers (conversion, detection, form gen)
│ │ ├── routes/ # REST endpoints (auth, jobs, connectors, webhooks)
│ │ ├── mcp/ # Model Context Protocol server
│ │ └── webhooks/ # HMAC-signed dispatch with retry logic
│ └── web/ # Next.js 14 App Router PWA (port 3000)
│ ├── app/ # Pages: landing, auth, dashboard
│ ├── lib/ # API client, Zustand stores, IndexedDB
│ └── public/ # Service worker, manifest, PWA icons
├── packages/
│ ├── shared/ # TypeScript types, Zod schemas, constants
│ ├── n8n-nodes-vectorforge/# n8n community node package
│ └── make-app/ # Make.com app definition (app.json)
├── docker-compose.yml
└── turbo.json
Backend
- Node.js 20 · Express · TypeScript
- PostgreSQL 16 + Prisma ORM
- Redis 7 + BullMQ (job queues)
- Tesseract.js · Sharp · Potrace
- pdf-lib · pixelmatch
- Anthropic Claude API (
claude-sonnet-4-20250514) @modelcontextprotocol/sdk(MCP server)- JWT + bcrypt · AES-256-GCM token encryption
- web-push (VAPID push notifications)
- Swagger / OpenAPI 3.1
Frontend
- Next.js 14 App Router · React 18 · TypeScript
- Tailwind CSS (dark mode via
class) - Zustand state management
idb(IndexedDB wrapper)- react-dropzone
- Workbox service worker
Infrastructure
- Turborepo monorepo
- Docker Compose (local dev)
- npm workspaces
- Node.js ≥ 20
- Docker & Docker Compose
- An Anthropic API key (for AI field detection)
git clone https://github.com/leoncons/vectorforge-pdf.git
cd vectorforge-pdf
npm installcp .env.example .envFill in the required values in .env:
# Required
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vectorforge
REDIS_URL=redis://localhost:6379
JWT_SECRET=<generate: openssl rand -hex 64>
ENCRYPTION_KEY=<generate: openssl rand -hex 32>
ANTHROPIC_API_KEY=sk-ant-...
# OCR engine (tesseract | google-vision | aws-textract)
OCR_ENGINE=tesseract
# Web Push VAPID (generate: npx web-push generate-vapid-keys)
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:you@example.comSee .env.example for the full list including cloud connector OAuth credentials.
docker compose up -d # Starts PostgreSQL + Redis
npm run db:migrate # Run Prisma migrations
npm run dev # Start API (4000) + Web (3000) in watch modeVisit http://localhost:3000
npm run build # Turbo builds all packages & appsFull OpenAPI 3.1 spec is served at /api/docs when the API is running.
http://localhost:4000/api/v1
# JWT (cookie or Authorization: Bearer <token>)
POST /api/v1/auth/register
POST /api/v1/auth/login
POST /api/v1/auth/refresh
DELETE /api/v1/auth/logout
# API Keys (x-api-key header, prefix: vf_)
GET /api/v1/auth/mePOST /api/v1/jobs # Upload PDF → start conversion
GET /api/v1/jobs # List jobs (cursor pagination)
GET /api/v1/jobs/:id # Get job status + quality report
GET /api/v1/jobs/:id/download # Download converted PDF
POST /api/v1/jobs/:id/detect-fields # Run AI field detection
POST /api/v1/jobs/:id/generate-form # Generate fillable AcroForm PDF
DELETE /api/v1/jobs/:id # Delete jobGET /api/v1/connectors/:provider/auth # Start OAuth flow
GET /api/v1/connectors/:provider/callback # OAuth callback
GET /api/v1/connectors/:provider/files # List files
POST /api/v1/connectors/:provider/import # Import PDF → create job
POST /api/v1/connectors/:provider/export/:jobId # Export resultSupported providers: gdrive · dropbox · notion · onedrive
POST /api/v1/webhooks # Register webhook
GET /api/v1/webhooks # List webhooks
DELETE /api/v1/webhooks/:id # Remove webhook
POST /api/v1/webhooks/:id/test # Send test eventWebhook payloads are signed with X-VectorForge-Signature: sha256=<hmac>.
Events: job.queued · job.processing · job.completed · job.failed · fields.detected · form.generated · export.completed
Upload PDF
│
▼
Extract Pages (Sharp / pdftoppm @ 600 DPI)
│
▼
OCR (Tesseract / Google Vision / AWS Textract)
│ → word bboxes, font size estimates
▼
Vectorize Regions
│ → edge detection → connected components
│ → line art → Potrace SVG
│ → photos → JPEG
│ → text regions → masked out
▼
Font Matching
│ → 54 Google Fonts catalog
│ → exact / partial / rule-based → download & cache
▼
PDF Reconstruction (pdf-lib)
│ → background layer (50% opacity)
│ → vector regions (SVG paths)
│ → raster regions (embedded JPEG)
│ → text overlay (embedded fonts, exact coords)
▼
Pixel Validation (pixelmatch)
│ → compare input vs output per page
│ → flag pages with >5% deviation
│ → generate diff images
▼
Quality Report
(overall score = 50% pixel + 30% OCR + 20% font)
Field detection uses the Claude API with a structured system prompt to identify form fields from page images and OCR text. Detected fields are returned as normalized bounding boxes with type, label, and options (for selects/radios).
Detect Fields (Claude claude-sonnet-4-20250514)
│ → sends page images + OCR text
│ → returns: [{type, label, bbox, options, required}]
▼
Generate AcroForm (pdf-lib)
│ → TextField → PDFTextField
│ → Checkbox → PDFCheckBox
│ → RadioGroup → PDFRadioGroup
│ → Select → PDFDropdown
│ → Signature → TextField (signature style)
▼
Output: fillable.pdf
Supported field types: text · number · email · date · checkbox · radio · select · textarea · signature
The API exposes a Model Context Protocol server at /mcp/sse for use with Claude Desktop or custom agents.
Tools:
| Tool | Description |
|---|---|
convert_pdf |
Upload and convert a PDF from a URL |
detect_fields |
Run AI field detection on a completed job |
create_fillable |
Generate a fillable AcroForm PDF |
get_job_status |
Poll job status and quality report |
import_from_cloud |
Import a file from a connected cloud provider |
export_to_cloud |
Export a converted PDF to a cloud provider |
list_jobs |
List jobs with optional status filter |
Resources: job://{id} · job://{id}/quality · connector://{provider}
Install the community node:
npm install n8n-nodes-vectorforgeAvailable nodes:
- VectorForge Trigger — fires on
job.completed,job.failed,fields.detected, etc. - VectorForge Action — convert, get status, detect fields, generate form, export to cloud, download
Workflow templates are in packages/n8n-nodes-vectorforge/workflows/.
Import packages/make-app/app.json into Make.com as a custom app. Provides triggers, actions, and instant triggers for all webhook events.
Register any HTTPS endpoint to receive signed events:
curl -X POST http://localhost:4000/api/v1/webhooks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-server.com/hook", "events": ["job.completed"]}'- Offline support — service worker caches static assets and API responses
- Install prompt — "Add to Home Screen" banner on supported browsers
- Background Sync — queued uploads resume when connectivity returns
- Push Notifications — receive alerts when long-running jobs complete
- IndexedDB — jobs and pending uploads cached locally
# Full stack (PostgreSQL + Redis + API + Web)
docker compose up
# Individual services
docker compose up db redis # Infrastructure only
docker compose up api # API only (needs db + redis)Images:
apps/api/Dockerfile— API with Tesseract + poppler-utils (Alpine)apps/web/Dockerfile— Next.js standalone build (Alpine)
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
✅ | PostgreSQL connection string |
REDIS_URL |
✅ | Redis connection string |
JWT_SECRET |
✅ | JWT signing secret (min 64 chars) |
ENCRYPTION_KEY |
✅ | AES-256 key for token encryption (32 bytes hex) |
ANTHROPIC_API_KEY |
✅ | Claude API key for field detection |
OCR_ENGINE |
tesseract (default) | google-vision | aws-textract |
|
VAPID_PUBLIC_KEY |
Web Push public key | |
VAPID_PRIVATE_KEY |
Web Push private key | |
VAPID_SUBJECT |
Web Push contact email | |
GOOGLE_CLIENT_ID |
Google Drive OAuth | |
GOOGLE_CLIENT_SECRET |
Google Drive OAuth | |
DROPBOX_CLIENT_ID |
Dropbox OAuth | |
DROPBOX_CLIENT_SECRET |
Dropbox OAuth | |
NOTION_CLIENT_ID |
Notion OAuth | |
NOTION_CLIENT_SECRET |
Notion OAuth | |
MICROSOFT_CLIENT_ID |
OneDrive OAuth | |
MICROSOFT_CLIENT_SECRET |
OneDrive OAuth | |
GOOGLE_CLOUD_CREDENTIALS |
JSON key for Google Vision (if using) | |
AWS_ACCESS_KEY_ID |
AWS key for Textract (if using) | |
AWS_SECRET_ACCESS_KEY |
AWS secret for Textract (if using) | |
AWS_REGION |
AWS region for Textract (if using) |
MIT © 2025 leoncons