← back
Redline — Contract Review

Redline — Contract Review

Live

Ask your contract questions, get cited markdown answers

Started: May 15, 2026 · ~5 hours, one evening

AI:Claude CodeOpenAI
Stack:HTMLJavaScriptn8nVercel

A contract-review prototype built as the Week 1 lab for Mahesh Yadav's AI PM Bootcamp. Upload a PDF, ask questions in chat, get cited markdown answers with confidence indicators and click-through citation pills that scroll the preview to the cited page. Architecture chosen for safety on a shared-password demo: the browser never sees the n8n webhook URL — a Vercel function proxies multipart uploads through with HMAC-signed HttpOnly session cookies and per-IP rate limiting in front of the AI agent. Live demo is gated behind a shared password.

// screens

Redline — Contract Review — screen 1
1 / 3

// highlights

  • Side-by-side PDF preview + chat composer — drag-and-drop upload, 4 MB cap, Enter to send, Shift+Enter for newline
  • Assistant replies render full markdown (headings, lists, tables, blockquotes, inline code) with a per-message copy button for clean pasting
  • Citation pills on each answer scroll the PDF preview to the cited page; confidence indicator dot per reply — green ≥85% / amber 65-84% / red <65% — with graceful fallback when the upstream omits structured fields
  • Server-side auth via HMAC-signed HttpOnly · Secure · SameSite=Strict session cookies (7-day expiry) on Vercel Functions; per-IP rate limiting (chat 10/min, login 5/5min); webhook URL stays in env and never reaches the browser
  • DOMPurify around marked v18 sanitizes LLM output against four common XSS vectors (<img onerror>, <script>, javascript: URI, <iframe data:>); CSP + HSTS + Permissions-Policy headers shipped via vercel.json
  • n8n cloud workflow (Webhook → AI Agent → Respond) hosts the OpenAI call so the browser proxies through Vercel and never sees the model URL or credentials — CORS sidestepped entirely
  • Single-evening build — 11 commits, 6 production deploys, 0 reverts; pre-ship QA score moved 82 → 92 after fixing the blank-flash-on-load bug

// takeaways

  • marked v18 passes raw HTML through by design — DOMPurify is the standard mitigation for any LLM-driven markdown rendering. Two-line code change, ~16 KB gzipped, defends against the four common XSS vectors. Build this in from day one, not after a real incident.
  • The HTML `hidden` attribute is fragile — class-level `display: flex` silently overrides it. The defensive base rule `[hidden] { display: none !important }` early in the stylesheet prevents the trap from recurring on every new component.
  • `vercel env pull` is a `.gitignore` landmine — it writes `.env.local` with production secrets by default. Without `.env*` in `.gitignore`, one `git add .` exposes every secret. One-line fix, weeks of pain if missed.
  • Vercel auto-deploy from GitHub honors `vercel.json` headers on every push — no CI wiring needed for CSP, HSTS, X-Frame-Options. The platform IS the deploy pipeline.
  • For a prototype, the LLM provider's hard spend cap is the real safety net. Auth + rate limits are belt-and-suspenders; the spend cap is the seatbelt. Set it on the OpenAI account before anything else.

Alexander Lee · AiPM · 2026

built with claude code + next.js