Maven Editorial Intelligence
AI-assisted proofreading for pharma promotional manuscripts. Four parallel AI checks against the brand's rules and references, output as an annotated PDF and a findings dashboard.
Overview
Maven Editorial Intelligence (MEI) is an AI proofreading platform I built for Maven Communications, a US promotional medical communications agency. Editors drop a manuscript in, four AI modules run in parallel against the brand's rules and reference documents, and they get back an annotated PDF plus a findings dashboard they can triage in. I started the build on April 23 and shipped a multi-tenant MVP into pilot in five weeks. 108 PRs merged, 49 migrations, 106 test files. Stack is Next.js 16, Supabase, OpenAI, pdf-lib, deployed on Vercel and Fly.io.
The challenge
Promotional manuscripts in pharma go through med-legal review (MLR). Three reviewers (medical, legal, regulatory) read every page, check every claim against the prescribing information, verify that required regulatory elements are present, and mark up the PDF by hand. A 12-page sales aid can take a senior reviewer two to three hours. Christopher, who runs Maven Communications, wanted to compress the first pass without changing the artifact reviewers work in.
The constraint was real. Med-legal reviewers live inside Adobe Acrobat. Whatever the AI did had to come back as a PDF they could mark up the same way they always do.
The reframe
It is not a chat tool with a PDF export. It is an MLR reviewer that hands you a marked-up PDF before you start.
Once I framed it that way, the output became the product. Findings render as PDF 1.7 highlights and sticky-note popups, the same shape med-legal reviewers already mark up by hand. Each finding has the verbatim quote, the rule it violates, a suggested fix, a severity, and (for claims) the reference that supports or contradicts it. The dashboard is for triaging and re-running. The file the reviewer opens in Acrobat is the deliverable.
Key decisions
Four modules in parallel, not one mega-prompt
Pharma MLR is not one job. It is four distinct ones: Grammar (yellow), Brand (orange), Claims (red), Annotations (blue). Each module gets its own JSON schema, its own prompt, and its own color in the PDF. Tradeoff: four prompts and four schemas to maintain instead of one. Win: a brand-rule violation never gets muddled with a missing Important Safety Information box, and reviewers can filter findings by module on the dashboard.
pgvector retrieval over context stuffing
Early versions stuffed the brand's full reference library into every prompt. It blew up on a 957k-token blob and was expensive at any reasonable volume. I migrated retrieval to pgvector, chunked references at ingest, and made every module's prompt pull only the relevant chunks. Tradeoff: a real retrieval layer with its own evaluation harness. Win: predictable costs, and a reference library that scales with the brand, not with the prompt budget.
Annotated PDF as the artifact, not the screen
The job page has a Grammarly-style workspace with the manuscript on the left and findings on the right. But the file the reviewer downloads is the actual product. Annotations follow the open PDF 1.7 spec, so highlights and popup comments survive in Acrobat, Preview, Foxit, anything. Tradeoff: pdf-lib mechanics, font fallbacks, and a watermark guard so cross-brand finding IDs never collide. Win: reviewers got a file that fit their existing workflow on day one.
Rejection memory that survives re-runs
Reviewers reject findings they disagree with. I built an addressed-PDF parser that reads the Accepted/Rejected state from a prior MEI run, fingerprints each rejected finding, and feeds those hints to the LLM on the next review. False positives shrink over time without retraining a model. Tradeoff: a fingerprint design anchored to span and rule (not LLM output text), plus a suppression audit log. Win: a feedback loop that doesn't depend on labelled training data.
Smartsheet at the brand layer, not in a sidebar
Maven's editorial pipeline runs on Smartsheet. I made the integration a brand-create requirement: every brand has a Smartsheet Sheet ID, and every completed review posts a row back. Tradeoff: a half-broken state if the integration were optional, so I made it mandatory at the brand level. Win: reviews land where Maven's editors already track work. No second system to check.
Multi-tenant from day one
Every public table has Postgres row-level security. A user only sees brands they belong to via client_members. Platform admins are a separate flag, not a permission level. Tradeoff: extra RLS work on every migration. Win: the moment Maven onboards a second pharma client, the isolation is already there. No “we'll add it later”.
Impact
Shipped a multi-tenant MVP in five weeks (Apr 23 to May 26, 2026).
108 PRs merged across 129 opened. Each major surface gated behind a verified review.
Around 56,000 lines of TS/TSX/SQL, 49 migrations, 106 test files.
Four AI modules running in parallel against brand-scoped rules and pgvector-backed references.
In pilot with Maven Communications on real promotional manuscripts.
Rejection memory loop closes the gap on false positives without model retraining.
Smartsheet integration writes every completed review back to Maven's editorial pipeline.
Timeline
Reflection
The hardest call on this build was treating the PDF as the product. The temptation was a chat-style review tool with a file export, but med-legal reviewers don't want a new interface. They want their existing one to be 60% lighter. Building toward an annotated PDF (not toward a screen) is what made this adoptable.
If I were starting over, I'd build retrieval before the first prompt, not after a 957k-token outage. Every reference-heavy LLM product I build from now on starts with pgvector on day one.