This is a submission for Weekend Challenge: Passion Edition
What I Built
When school let out for summer, I promised myself I'd finally read everything on my list. And I did — I read constantly, highlighting every sentence that hit me along the way. I'm a chronic highlighter.
The problem showed up a few weeks in: I had dozens of highlighted documents and no way to use any of it. Highlights scattered across files, buried on pages I'd never revisit. I'd finish a book with fifty things I'd marked as important and a month later couldn't tell you five of them. All that reading, and I was still forgetting everything.
So I built the tool I actually needed: an app that takes a highlighted PDF or DOCX and pulls every highlight, underline, strikeout, and comment into one clean, structured list — no more re-opening a 300-page file to copy-paste forty highlights by hand.
From there, it does two things I actually wanted:
- Organizes by color and type, since I already color-code as I read (yellow for definitions, pink for disagreements) — the tool respects that system instead of ignoring it.
- Uses AI to turn scattered highlights into a real summary — grouping them into themes and writing connected paragraphs, so a flat list of fragments reads like actual study notes. It exports wherever that information needs to live next — Markdown, Word, PDF, Anki flashcards — and it's designed to feel like it's about reading, not about processing files.
Demo
Code
How I Built It
The core challenge was that "highlight" isn't one standard thing — PDF and DOCX store annotations completely differently, so the first real decision was architecture: one shared data model (page/location, color, annotation_type, text, note, timestamp), with a separate extractor per format that all produce it. Adding a new annotation type or file format later means writing one new module, not touching existing code.
Extraction: PyMuPDF for PDF (highlights, underlines, strikeouts, and notes are all real annotation subtypes with quad points), python-docx for DOCX (highlights and comments are unambiguous; underline/strikethrough are just text formatting there, so I made that an opt-in toggle, off by default, rather than silently capturing stylistic formatting as if it were intentional).
Color as a shared vocabulary, not raw RGB: DOCX highlight colors are a fixed named enum, so I standardized on color names across both formats — for PDF, I snap the extracted RGB to the nearest name in the same palette. That gave both formats one consistent color vocabulary I could actually reason about downstream (filtering, AI hints) instead of reconciling two representations later.
Backend/frontend split: FastAPI serves both the API and the static frontend from one process (StaticFiles mount) — same origin, no CORS to configure, no dev/prod mismatch from opening the frontend as a raw file.
Google AI — Gemini: the AI layer takes the extracted highlights and does two things in a single structured-JSON call: clusters them into themes, then writes a connective summary per cluster (not a per-highlight summary — a highlight is already a distillation, re-summarizing it individually just loses the exact wording someone chose to keep). I used Gemini Flash-Lite specifically: it's on the no-cost tier, and clustering short text snippets doesn't need frontier-level reasoning, so it was the right-sized model rather than the biggest one.
Design: I went with an editorial visual style on purpose — serif type for the actual highlighted passages, a colored rule instead of a colored block, everything else quiet — so the tool feels like it's about the books, not about processing files.
Prize Categories
Best Use of Google AI — the "Organize with AI" feature uses the Gemini API (Flash-Lite) to cluster extracted highlights into themes and generate a synthesized summary per cluster, turning a flat, page-ordered list of annotations into something that actually reads like study notes. This is a core feature of the app, not an add-on — the whole reason I built the extraction pipeline was to feed it into this step.
Top comments (0)