← Design · c122

artboards-plan.md

c122 — Plan: the contents of the Illustrator files

Status: steps 1–2 built 2026-10-23 (extraction + canvas map); steps 3–7 not started. Prompt: artboards-prompt.md. Mode: archaeology. The iterations already exist, laid out on the canvas; this surfaces them.

Phase 2 gave each .ai file one preview, of its first artboard. Most files hold many artboards, and Mark lays quick iterations out horizontally. This plan turns every artboard into an image and keeps its position on the canvas. Mark then tags artboards and assembles sequences by hand, in post. Strips are stitched from those sequences, and the tagged sequences feed page evolution.

Revised 2026-10-23 on Mark's note: "it will be difficult to derive that yourself, I think we would want to stitch these sort of things together manually in post. Tagging?" Automatic row detection and name-based subject mapping are out. Extraction stays automatic; meaning comes from tags.

What the probe found

The probe covered 15 drive .ai files: 3 history boards plus 12 random ones from every generation, 173 artboards in all.

  1. Each artboard is already a PDF page. Files saved with "Create PDF compatible file" carry one PDF page per artboard. All 173 artboards matched their pages, in order and in size. Pages per file: 1–46, typically 7–18. Extrapolated, that's roughly 2,500 artboards in the 255 .ai files (2.15 GB).
  2. Names and canvas positions can be read without Illustrator. The file's Illustrator private data (AIPrivateData streams, zstd-compressed on modern files, zlib on older ones) holds one record per artboard: Name, PositionPoint1/PositionPoint2 (top-left and bottom-right on the canvas), ArtboardUUID and IsArtboardDefaultName. A short parser (mutool + zstd) reads them. Prototype: the session scratchpad's artboards.py.
  3. Page order isn't canvas order. QPT.index-v20.ai runs 2, 1, 3, 4… left to right. Sequences have to come from positions.
  4. Rows are easy to find. Artboards in a row share a top edge: QPT.index-v20.ai is one row of 7, QPT.brochure-site-1.0.ai one row of 5, and QPT.dash-1.1.ai 12 artboards in 6 rows. The LinkedIn headers file is a vertical stack (10 rows of one), so columns need handling too.
  5. Names are mostly defaults ("Artboard 18 copy 16"). The exception is the history boards: all 42 custom names were there, and each names the source file the artboard was copied from (QPT.sketch-scratchpad.ai, QPT.glass-io-integration.ai). That's a provenance link from the boards back to the originals.
  6. Rendering is fast: pdftoppm drew all 7 artboards of QPT.index-v20.ai in 0.9 s. A stitched strip of that row (artboards-probe-index-v20.webp, canvas order) reads as the story: the header stays fixed while the second section is redrawn six times.

What we'd build

A. Extract: scripts/drive-artboards.mjs (npm run drive-artboards)

Same contract as Phase 2: read-only, and an online-only file is copied to a temp folder (which makes Drive download it) and deleted after. It's cached by size and date, takes --only/--list/--retry, and runs every tool under a timeout. Per .ai file:

  • pdfinfo gives the page count, and the private-data parser gives the artboard records. If the counts disagree, record the mismatch and fall back to page order.
  • pdftoppm renders each page. Long edge capped (see open question 1) so the 9,000 px brochure pages and the 46-artboard history board stay sane.
  • Write public/library/artboards/<file key>/<n>.webp plus a small thumb.
  • Write server/data/drive-artboards.json. Per file: { artboards: [{ n, uuid, name, defaultName, x, y, w, h, image, thumb }] }. These are facts only; no sequences are guessed.

Files without PDF content have no pages to render. These are likely the 9 .ai files QuickLook drew blank in Phase 2. For those, a second pass drives Illustrator itself through the existing ExtendScript-over-osascript plumbing in scripts/illustrator-export.mjs: open the file, exportForScreens each artboard, close. It runs only on the failures, on Mark's machine, with Illustrator open.

B. Tag and sequence by hand

The judgement is Mark's: which artboards are iterations of what, in what order, and what they're about. The tools make that fast, and the result is plain data in git.

Tags. Free-form, plus a few typed prefixes that other parts of the site understand:

  • subject:<id> uses the evolution subjects in app/data/subjects.ts, e.g. subject:page/dashboard. New subjects can be added there.
  • cycle:c114 and phase:pre-seed set the ties Phase 3 needs. A tag beats the date-inferred phase.
  • pick marks the artboard that best represents a file or a sequence.
  • Anything else is a plain word: pitch, nav, dark, abandoned.

Tags go on an artboard, or on a file (where they apply to all its artboards unless one overrides).

Sequences. A named, ordered list of artboards: { id, title, note, tags, items: [{ file, n }] }. A sequence can span files, e.g. QPT.index-v12 → v13 → v19 → v20, because iterations often moved to a new file. The note is a sentence or two on what changed and why, which is where the story gets written.

Stitching happens from a sequence, not from the canvas:

  • On the page, a sequence renders live as a strip (images in a row at a common height), so nothing needs re-stitching while it's being edited.
  • npm run drive-strips writes a stitched WebP/PNG per sequence (public/library/sequences/<id>.webp) for evolution, decks and Illustrator. Gap, height and background are options.

Where it's stored. app/data/drive-tags.json (file and artboard tags) and app/data/drive-sequences.json (sequences), committed like the rest of the design data. On :3000 the library gets an edit mode that writes these files through a dev-only API route (/api/library/tags, refused outside dev). The deployed site stays read-only and shows the committed result. Editing the JSON by hand also works, and so does asking Claude ("tag artboards 3–7 of QPT.index-v20 as subject:page/front-site").

C. /library: show what's inside a file, and curate it

For an .ai file the detail panel adds:

  • A canvas map: the artboards drawn at their real relative positions and sizes, each filled with its thumb. The file's layout at a glance, the way Mark sees it in Illustrator. It's also the fastest way to pick: click, shift-click, or drag a box around a row.
  • In edit mode (dev only):
    • Tag the selection.
    • Make a sequence from it, in canvas left-to-right order, then reorder by drag.
    • Add the selection to an existing sequence.
  • Sequences this file appears in, each as a strip. Clicking one opens it in the lightbox (UxLightbox, c96), stepping artboard by artboard.
  • An artboard count on the file and in the generation cards.

A new Sequences view lists every sequence (title, strip, note, tags, files it spans) and filters by tag.

Links: /library?f=<path>&a=<n> points at one artboard, /library?seq=<id> at a sequence.

D. Page evolution: the drive as early moments

buildEvolution (c96) groups captures by subject into moments. It already supports:

  • origin: c97's pre-cycle provenance, e.g. "Gen-1 prototype", shown in place of a cycle;
  • asOf: the date the state is from;
  • fans: several versions in one moment.

A hand-made sequence maps onto that directly:

EvolutionFrom the drive
subjectthe sequence's subject: tag
momentone sequence (or one per source file, when a sequence spans files with different dates)
fanthe sequence's artboards, in Mark's order
origin{ id: 'drive-1.0', label: 'Design 1.0 · QPT.index-v20.ai' }
asOfthe source file's catalog date (name date where there is one)
captionthe sequence note
linkback to /library?seq=…, the artboard and the Drive original

The evolution builder gains a second source next to the capture manifest: app/data/drive-sequences.json. Only tagged sequences appear; nothing is mapped by guessing. A single artboard tagged subject: + pick can stand alone as a moment.

Then, once tagged, the dashboard subject can run from 2022's QPT.dash-1.1.ai through lab.dash-3.18 (Mar 2026) into the c114/c121 lab captures, on one timeline.

E. Later, same idea for other multi-page files (not in this plan)

  • PDFs (60): pages render with pdftoppm the same way.
  • InDesign (44): XMP only gives the first page. A full deck needs InDesign scripting or the matching exported PDF, which often sits beside it in the same folder.
  • Sketch (9): .sketch files hold pages and artboards as JSON, plus per-page previews.

Steps

  1. Extractor + manifest on a sample of 20 files (including the history boards and the biggest), then the whole .ai set in the background. Report: artboards, mismatches, files without PDF content.
  2. /library canvas map + artboard lightbox + ?a= links. Verify headless.
  3. Tags and sequences: the JSON files, the dev-only write route, edit mode (select on the canvas map, tag, make or extend a sequence, reorder), the Sequences view. Mark tags a first file or two to test the workflow before anything else builds on it.
  4. npm run drive-strips: stitched images per sequence.
  5. Illustrator pass for the files without PDF content (Mark's machine, Illustrator open).
  6. Evolution reads tagged sequences as origin moments; verify on /cycles/evolution with the sequences from step 3.
  7. Record, captures, commit (c122 paths only).

Open questions for Mark

  1. Size budget. About 2,500 artboard images go into git and onto the site. Default: 1,200 px long edge WebP for the lightbox plus 320 px thumbs, roughly 100–150 MB. Alternatives: 800 px (~60 MB), or move full-size images to R2 later.
  2. Tag vocabulary. Free-form plus subject:, cycle:, phase: and pick. Are there tags you already use in your heads or folder names that should be first-class (e.g. iteration, final, rejected)?
  3. History boards. Their artboards are copies named after source files. Default: show them in the library, auto-tagged source:<file name> from the artboard name (the one thing that is safe to derive), and in evolution link each to its source file rather than counting it as a separate moment, so nothing appears twice.
  4. Off-artboard content. Work on the canvas but outside any artboard (scratch areas) isn't captured by page rendering. Is that fine for now?
  5. Where editing happens. Default: edit mode on the local dev server, writing JSON in the repo, committed with the rest. The alternative is an editable deployed page backed by a shared database, so others could tag too. That's more moving parts; worth it only if someone besides you will curate.

Qpoint Brand Style Guide