CLIENT WORK — PRODUCTION —
Watch Catalogue Operations Hub
A 240-variant watch collection composited in under 5 minutes, along with a hub any successor can pick up cold.
≈ 3 min read
AT A GLANCE
- STATUS
- PRODUCTION
- TIMELINE
- 2026-05 — 2026-05 · 16 DAYS
- LANGUAGES
- Python / AutoHotkey / Markdown
- CATEGORY
- CLIENT WORK
RENDERS DELIVERED
OUTCOME
Delivered ~290 renders across 4 collections.
METRICS
M.01 — RENDERS DELIVERED
Finished catalogue renders across 4 watch collections (2024-25), transparent-background, 2600×4000 px and above. Sum of per-collection folder labels (12 + 10 + 240 + 28). The largest batch has ~209 image files vs its 240 label, see source.
M.02 — LARGEST SINGLE COLLECTION
One collection automated end-to-end via the Python batch-render and compositor pipeline
M.03 — FULL-COLLECTION COMPOSITOR RUNTIME
Composites the full ~240-variant collection once layer PNGs are exported, down from manual work measured in days. Per engagement-history.md.
M.04 — LINES OF PRODUCTION PYTHON
Across the repo's scripts (reference parser, batch renderer, scene utilities), excludes the production compositor script held locally.
M.05 — FILES IN THE KNOWLEDGE HUB
Docs, scripts, and templates that make up the structured knowledge base, the deliverable that makes re-engagement cheap.
CH.01
The problem
A Swiss luxury watchmaker (Geneva) needed hundreds of catalogue renders per collection, but every brief was an undocumented code string and the work ran inside a locked-down remote desktop.
Each watch variant (case material, dial colourway, diamond-setting configuration) needs a finished studio render at 2600 × 4000 px or larger, and the largest collection runs to 240+ variants. Their reference numbers pack all of that information into a single opaque string, and the naming was inconsistent even internally. The same variant could appear under three different codes depending on which folder you were looking at. The work environment was a remote desktop with no clipboard access in or out. There was no documented process, and no single person held the full picture of how the reference system worked.
CH.02
What I built
A documented operations hub that turned an ad-hoc, in-one-person's-head process into a repeatable, auditable pipeline.
The reference decoder (docs/reference/naming-conventions.md) maps the four positional blocks of every watch reference number (case family, complication, material, and dial/finish) to actionable render specs. A Python parser (scripts/parse_reference.py) implements the same tables in code, flagging any unrecognised tokens immediately rather than silently guessing. A companion abbreviations index captures every code token encountered, tagged Confirmed, Draft, or Placeholder, so nothing is decoded from memory and nothing unverified gets promoted silently.
The workflow layer standardises how work arrives (a folder-naming convention), how it is briefed (one brief.md per job with the decoded spec), and how it is delivered (naming, resolution, format, and backup discipline). A scope-of-work template and communication-style guide cover client interactions. The hub follows a Diátaxis-inspired split: docs/reference/ for facts about the client's products, docs/workflow/ for how the work runs, docs/communication/ for client interaction records, and docs/projects/ for one folder per job. Every script carries a header comment stating purpose, usage, and dependencies.
A later scripted-scene architecture document (docs/workflow/scripted-scene-architecture.md) codifies the better approach for large collections: one Blender scene with all variants driven by a single embedded batch-render table, so any edit to a shared component propagates to all variants automatically, and a successor can take over with no context transfer beyond the file itself.
CH.03
The automation that pays off
A Python batch pipeline composites a full 240-variant collection in under 5 minutes, work that was previously manual and days long.
An AutoHotkey autotyper (scripts/SendToRDP.ahk) types Python scripts character-by-character into the remote desktop session, bypassing the clipboard restriction entirely. The Blender batch-render script chains every scene via a render_complete handler and timer, staying stable under heavy Cycles loads where a naive Python loop deadlocks the UI thread. A CSV-driven compositor then stacks three per-variant render layers (case, numbers, and hands) into finished PNGs, resumable via lock-files if a batch is interrupted mid-run.
The result: a full ~240-variant collection that once required days of manual compositing now completes in a single unattended run. The Python automation paid for itself on the largest collection. A later collection reused the same scene setup at near-zero marginal cost.
CH.04
Built to survive a handoff
When the contract resumed after a 14-month gap, the full context was available on day one, with no discovery phase.
The engagement history (docs/communication/engagement-history.md) is a full dated audit trail of every rate change, scope conversation, project milestone, and open risk, structured to be readable cold by anyone who picks up the work later. Every reference-knowledge entry carries a confidence tag so no unverified assumption can pass silently into a render spec. A successor designer can read the hub cold and begin producing correct renders without three weeks of rediscovery or calls to reconstruct the client's reference grammar.
This is the real deliverable: not the renders, but the knowledge base that makes future renders cheap.
CH.05
Results and scale
~290 photorealistic renders delivered across 4 collections, and the cost per variant dropped sharply once the automation was in place.
Four collections completed across the 2024–25 engagement, from small proof-of-concept batches through to a fully automated run of ~240 variants. The largest collection is where the pipeline justified its build cost. The final collection reused the scene setup almost for free. 61 documents and 758 lines of Python make up the hub itself: the structured knowledge base, workflow standards, and reusable tooling that make re-engagement cost-efficient and any handoff clean.
22 COMMITS — IN 34 DAYS — AVG 1/DAY
72 NODES · 45 EDGES · 40 COMMUNITIES — EXTRACTED FROM THE CODEBASE BY TREE-SITTER
FEATURES
| Reference number decoder | Splits any opaque watch reference string into case family, complication, material, and dial/finish, flagging unknown tokens instead of guessing, with confidence tags on every code. |
|---|---|
| Clipboard-free script delivery | Types Python scripts character-by-character into the remote desktop, delivering code into a secure environment that blocks all clipboard transfer. |
| Blender batch-render pipeline | Renders every scene in a file by chaining a render-complete handler and timer, staying stable under heavy Cycles loads where a direct Python loop deadlocks the UI. |
| CSV-driven layer compositor | Reads a variant table and stacks three render passes (case, numbers, hands) into finished PNGs inside Blender's bundled Python, resuming from lock-files if a batch is interrupted. |
| Single-scene variant architecture | Holds every variant in one Blender scene with materials swapped by an embedded script, so one edit propagates to all variants and a successor can take over with no context transfer. |
| Docs-as-code knowledge base | Keeps product knowledge, workflow standards, and client history in one place, tagged by confidence and updated alongside the work, so the engagement resumes after any gap without rediscovery. |
ARCHITECTURE
| Reference knowledge base | Decodes the client's proprietary reference-number grammar and diamond-setting notation. Source of truth for all abbreviation lookups. |
|---|---|
| parse_reference.py | Lightweight command-line parser that splits a reference string into its four blocks using the same tables as the reference docs |
| SendToRDP.ahk | AutoHotkey autotyper: types a clipboard-loaded text file into the remote desktop session to bypass the clipboard restriction |
| batch_render_all_scenes_ui.py | Blender batch renderer: chains scene renders via a render_complete handler + timer, avoiding UI-thread deadlocks on heavy Cycles scenes |
| CSV compositor (keystroke.txt / batch_render.py) | Reads a per-variant CSV, alpha-composites case/numbers/hands layer PNGs in Blender's bundled Python, outputs finished watch images with lock-file resumption |
| Scripted-scene architecture doc | Blueprint for single-scene multi-variant .blend files: one scene, named collections per variant axis, embedded Python driver, fully manual fallback |
| Engagement history | Dated audit trail of every rate change, project milestone, scope conversation, and open risk, structured for cold readability across multi-month gaps. |
STACK
SKILLS DEMONSTRATED
Turning manual, repetitive production work into Python batch automation · Decoding undocumented client systems into clear, shared references · Building knowledge bases that survive handoffs and multi-month gaps · Photorealistic 3D rendering for product catalogues (Blender, Cycles) · Blender Python scripting (batch rendering, layer compositing) · Working inside locked-down, security-constrained client environments · Designing briefing, delivery, and audit-trail workflows for solo client work
