Reference library: how a page gets catalogued
One Figma page at a time, in this order. Steps 0 and 5 involve Vick; the rest is run by an agent. Steps marked "planned" were not part of the pilot and get built before the next page.
0. Map the sections first (planned)
Sections are how Vick groups the boards, and the grouping carries meaning, so the page is mapped before any image is exported.
- List every section and group on the page: name, node id, number of images, any text labels inside it ("GLASS COLLECTION", "Ideas: B").
- Give each section a kind: brand (one house, such as Perfumer H), theme (a category such as Gifting or Japanese Incense), mockup (a design that places images), own work (Auspicious designs) or notes.
- Write this to
pages/<page>/sections.json, and show it to Vick as a short table before going further. Vick can rename, merge or skip sections there. - The library shows sections as their own way in: a board view where images keep their Figma grouping and order, and a Section filter.
Reference eligibility
Apply the external-only scope in Reference scope and purposes before selecting image nodes. Keep authored layouts, personal swatches, hidden assets and component internals out of the catalogue. Preserve the page/section origin and record exclusion reasons. Purpose is separate from the fixed visual vocabulary; original human corrections remain authoritative.
1. Read every image's identity (planned)
A read-only script in the Figma file records, per image layer:
- its image ID: Figma stores each uploaded file once, so the same photo placed ten times shares one ID;
- its original size, such as 3000 × 4000, and how the board shows it (crop, fit or fill);
- its format: JPEG, PNG, GIF or video;
- any parent mockup frame it sits in.
This catches duplicates across pages exactly, even at different sizes or crops.
2. Export
- Render each section once and crop each image out by position. That is fast, but large renders silently drop images.
- Since East Fragrance: rows of images inside a frame are rendered once at full size (1080 px tall) with
get_screenshotand itsmaxDimension, which returns a download link rather than an inline image, andcrop_frames.pycuts them out. Images loose in a small section come from one section render (crop_sections.py); images in groups, whose positions are relative to the group's parent, are rendered one by one. 7 of 830 needed a second render. - Images 360: native-size batches up to 64 megapixels also cover dense boards. A frame named Group can be batched when its child coordinates fit local bounds; ambiguous parent-relative coordinates still render individually. Resume from valid saved PNGs, using whole rows and sections first.
prepare_images.pycrops only missing JPEGs, preserves previous records and creates thumbnails. Inspect every dark/flat flag before spending a repair call; dark artwork is often valid. Keep verified false duplicate pairs induplicate-exclusions.jsonand copy that file into the work folder before runningdups.py. - Automatic checks then catch black, blank, canvas-grey or covered crops, and re-render those nodes one by one. In the pilot that was 107 of 607.
- Exports are previews, longest edge 1200 px. Long pages (more than three times taller than wide, such as a pasted web page) are the exception: a section render shrinks them to a thin strip, so each is rendered on its own at full height, up to 1200 px wide and 8000 px tall. Old exports go to
images-superseded/, not the bin. - Originals are downloaded only when Vick marks an image as needed in full resolution; the file comes from Figma's original upload, not a screenshot.
- GIFs and videos are catalogued as a still of their first frame, marked as animated, and linked to Figma.
- Vectors (logos, icons, illustrations drawn in Figma) are not catalogued as images; they belong to a design system.
3. Mockups
- If a mockup is built from separate image layers, each image is catalogued on its own and matched to its original by image ID. The record says where it is used, for example "Website v6, Chalet page".
- If a mockup is one flat screenshot (someone else's web page pasted in), it is catalogued as a single "layout or type" image.
- Auspicious’s own mockups stay outside the external reference catalogue. Existing files and audit records are retained; scope exclusions do not delete them.
4. Tag
- Contact sheets of 20 images, tagged from
vocab.jsononly, with a one-line caption and the brand when a label shows it. - Each line: sheet position, space, second space, type, material, light, shot, three moods, brand, element (one or two), packaging forms (or
-), format, caption. - Element is judged on its own, not copied from the space: a Townhouse interior lit by diyas can be Fire.
- Space may be empty when none fits. Element, material and packaging may also be empty; a printed book is not automatically packaging. Camera-shot tags may be empty for digital layouts, with light set to none. Source requires a visible label in the image, not just the board name.
- An incomplete export can be saved as a partial catalogue, with
expected_countandcatalogue_status: "in progress"in the manifest. The library must display that status. Do not markexportedortaggedcomplete until the entire page has passed those stages. manifest.pyvalidates every tag and stops on anything outside the vocabulary.- Colours are measured from the pixels, not judged by eye.
5. Review (planned)
- A review mode in the library: confirm or correct the Space and Type, with one tap per image. Corrections are saved to
corrections.json. - Space is the judgement call. Vick reviews Space on every page, and spot-checks about 5% of the other fields.
- About 4 seconds per image for Space and Type: roughly 40 minutes per 600 images.
6. Build and publish
manifest.pywritesmanifest.jsonand.csvintopages/<page>/.pack.pyrebuilds the image data insite/from every page's manifest;pages.mjsrebuilds the library, docs and progress pages.- Add a line to the log in
progress.json, and send Vick the link.
Keeping progress
progress.json in the library folder is the record of where every page has got. The Progress page is built from it, so Vick can see how far a run went even if it stops halfway (a session ends, or credits run out).
- Before starting a page, set
run: the page's node id, who, the stage,doneandtotal,started,updatedandresume(one line saying exactly where to pick up). This is also the claim: ifrunis set and updated in the last 45 minutes, someone else is working; do not start. - At every stage, and at least every 50 images, update
done,stage,updatedandresume, and runnode pages.mjs. Work is saved as it goes (exports, tag lines), so an update is never more than a few minutes behind. - When a stage finishes, set its date in the page's
done(mapped,exported,tagged,reviewed,published). - When the page is finished, add a line to
historyand setrunback tonull. - A run that has not updated for 45 minutes shows as stopped on the Progress page. The next agent reads
resume, checks the files, and carries on from there.
Example:
"run": { "page": "1834:5533", "who": "Claude", "stage": "exported", "done": 340, "total": 826,
"started": "2026-10-23T10:00:00+05:30", "updated": "2026-10-23T10:48:00+05:30",
"resume": "Sections 1-9 cropped; next section 10 (Ideas: B)" }
When something is wrong
| Problem | Fix |
|---|---|
| A tag is wrong | Correct it in review mode; it is saved as a person's correction and survives re-runs |
| The same mistake across many images | Fix the rule or the space's anchor examples, then re-tag only those images |
| An image exported black, blank or covered | Re-render that node alone, automatically or on request |
| An image is a duplicate | Link it to the first copy, keeping every location |
| The Figma page changed | Re-run the page: new images get tagged, removed ones are marked removed, unchanged ones and corrections stay |
| A word is missing from the vocabulary | Ask Vick; never add it silently |
Readable names and sharing links
For web captures and case studies, inspect the header, project introduction, product labels and footer at readable size. A contact sheet alone is insufficient for a long capture. Local OCR can help locate text, but check the image before accepting a name. Keep only a few useful headings and names, not an OCR transcript.
The brand belongs in source; the project title, host/retailer and credited creator belong in project, platform and creator. A multi-brand studio index is not automatically the adjacent project’s brand, and a collection title does not prove the parent brand. Canvas proximity is context, not label evidence. Leave the source Unknown when the name cannot be established.
Readable-text reviews are stored in the repository’s annotations.json, keyed by node ID, with a short source_evidence explanation. manifest.py and pack.py both apply them. They cannot alter the fixed visual tags. keywords are free text, separate from vocab.json. Human edits in the local library root’s or page folder’s corrections.json take priority; personal keywords or user_keywords there are retained as user_keywords through rebuilds. These files are never rewritten by the pipeline. This preserves later additions; there is not yet an in-browser keyword editor.
In the viewer, Copy library link copies a stable ?ref=NODE_ID#library link that opens that exact image, including a duplicate. Open in Figma and Copy Figma link remain separate. View page opens the parent library page using ?page=PAGE_ID#library. Links retain the current host and path, including the portal’s /reference-library/ path. Local links require the local server; sharing them between computers requires an accessible hosted copy of the library.
Webpage capture planning
For a board of website references, scripts/plan_web.py META.xml WORKDIR prepares logical capture units before the standard render planner. A frame assembling slices of one screenshot stays one reference, with the frame's stable Figma node ID. Complete editable website imports are retained as layout references; their component libraries, vector fragments and annotation shapes are excluded. Ordinary boards of separate images are not collapsed. The closest nested section is preserved.
Imported Body content can extend beyond a viewport-height frame. Use its full height when planning the render. Check actual rendered dimensions against the expected bounds: off-canvas menus and decorative overflow can shrink a capture dramatically. Repair low-resolution captures individually, or crop the intended webpage viewport from the saved native render after visual verification. Keep the raw PNG and move the earlier JPEG into images-superseded/; record the crop and reason in the page's quality notes.
Rotated deck layers
For imported presentation slides, obtain each selected node’s absoluteBoundingBox and its parent’s absoluteBoundingBox in a read-only Figma inspection. Save them as work/absolute-bounds.json (objects with id, box and parentBox). plan_renders.py uses those rendered corners instead of the layer’s transform origin. A rotated slide can otherwise shift a crop by one column or produce a blank final slide. Always inspect the first and last slide and the whole contact sheet before accepting a batched deck export. Retain original PNGs for future inspection.
Paper specimens and mixed colour studies
Follow Paper and material references when supplier specimens, branded applications and authored colour studies share a board. Extract independent source images rather than the constructed palette. Keep specification evidence qualified, inspect pale/flat flags for real texture, and preserve the exact pending node queue if access stops.