Inspiration

Research findings are easy to read and surprisingly hard to reuse. A paper might contain exactly the chart or table you need, but its underlying data is trapped inside a PDF. Reusing it means copying values by hand, estimating points, and repeatedly checking the original.

I built UNSPIN to make that process easier while keeping the evidence visible. AI can help recover data, but users should be able to inspect and correct what it produces.

What it does

UNSPIN turns selected charts, tables, and numerical text into editable, source-linked datasets.

Upload a PDF, image, CSV, or Excel workbook, then choose the page, region, or records you want to use. Structured files are parsed locally; selected PDF and image regions can be processed with Google Gemini.

The workspace lets you:

  • Inspect values alongside their source references.
  • Edit cells directly, with validation against the column’s declared data type.
  • Track committed changes and undo them through version history.
  • Build bar, line, and scatter charts, including filtered views saved from the data table.
  • Zoom toward the mouse pointer and automatically fit dense data distributions, with explicit notices when points fall outside the initial view.
  • Ask AI questions about the dataset or selected points and follow clickable evidence.
  • Export data and download the current graph as a PNG. The text extraction mode structures explicitly reported numbers into a table. It does not create numerical observations from qualitative statements. Supporting quotes are model transcriptions and still require verification against the source.

How we built it

I built UNSPIN as a solo project using Next.js, React, and TypeScript, with shared runtime-validated contracts between the interface and server.

Gemini handles visual extraction and AI analysis. PDF.js renders PDF pages, while Papa Parse and ExcelJS support structured imports. Charts use Recharts.

The local durable configuration uses PostgreSQL, private filesystem storage for original uploads, and a separate extraction worker. Data and edit history persist independently of AI conversations.

Challenges we ran into

The hardest part was making extraction useful without making its output look more certain than it was.

A valid AI response is not necessarily a correct dataset. UNSPIN distinguishes estimated, transcribed, and edited values, preserves missing values, and keeps source references attached. Partial results require acknowledgement before use or export.

Long-running extraction also exposed practical problems: queued work, provider failures, cancellation, and recovery. The interface needed to explain those states while preserving the user’s source and selection.

Accomplishments that we're proud of

  • Connecting data to its evidence. Extracted values retain source references, so users can inspect the original document while reviewing and correcting the dataset.
  • Building a complete reuse workflow. UNSPIN brings selection, extraction, inline editing, version history, undo, visualization, and export into one workspace.
  • Making AI output reviewable. Estimates, transcriptions, edits, missing values, and partial results remain distinguishable.
  • Making dense graphs usable. Mouse-centered zoom and distribution-aware fitting reveal patterns without changing the underlying values or silently hiding extremes.
  • Preserving work beyond a session. Durable local storage retains original uploads, datasets, and edit history across restarts.

What we learned

Trustworthy AI tools need more than a good prompt. They need explicit boundaries, recoverable failures, validation, and a way for users to challenge the result.

I learned to separate three questions: Was the output structurally valid? Was it faithfully extracted? Is it meaningful to analyze? Those require different checks.

What's next for unspin

The next priority is extracting embedded PDF text and table coordinates before falling back to vision. That could improve numerical fidelity, processing time, and source precision for documents with selectable text.

Built With

Share this project:

Updates

Submission history