3D_Cake_topper/README.md
Mannu c5ca1e0214 chore: scaffold delivery repository
Layout, secret hygiene and workflow per the engagement's version control
plan. Nothing functional yet — this establishes the shape before code
lands, so the conventions are enforced from the first real commit.

- .gitignore + .env.example: no secret can reach a commit object
- lefthook + gitleaks pre-commit gate; blocks new files >10MB
- templates/ holds config files, never per-template scripts
- deploy/nginx/ version controlled rather than hand-edited on the server

Refs ADR-007
2026-08-15 08:59:11 +05:30

4.4 KiB
Raw Blame History

3D_Cake_topper

Delivery code for the 3dcaketopper.nl personalised cake-topper platform, built for Van der Eijk Investments B.V.

[!important] This repository is assigned to the client Under the engagement's gate-by-gate IP assignment, everything here transfers to the client. Keep it clean of internal material — commercial reasoning, pricing, risk assessments and client correspondence belong in the private Obsidian vault, never here. Git history is permanent; anything committed is handed over, even if later deleted.

Related repositories:

  • Obsidian_vault — internal notes, ADRs, risk register (never transferred)
  • 3dct-client-mirror — read-only snapshots of the client's pre-existing system

What this builds

A configurator that lets a customer personalise a figurine template — garment colours, skin tone, hair colour, hairstyle, name, age, date — and produces a print-ready 3MF for Bambu Lab FDM printing.

The architectural principle, and the reason the economics work:

Everything except the face is deterministic. Colour changes are a WebGL recolour in the browser (out = albedo × L + S) — free, instant, and identical every time, which matters because the customer is approving a physical product. Only the face-likeness step calls a model.

The system it replaces makes two paid image-generation calls per configuration and regenerates the entire figure whenever any attribute changes.

Layout

docs/            architecture summary (client-safe) + deploy runbook
pipeline/        extract.py, pipeline.py, build.py — template authoring
configurator/    runtime.html, studio.html, shaders
templates/       per-template CONFIG FILES — never scripts
stl/             assembly, manifold3d printability gates, 3MF export
tests/golden/    regression baselines
deploy/nginx/    vhost fragments — version controlled, not hand-edited on the box
deploy/systemd/  unit files for the API service

Two conventions this layout enforces:

templates/ holds configuration, not code. One configurable pipeline with N config files — never one script per template. A .py file appearing in templates/ means the architecture has regressed. This was learned the hard way: the first prototype was built and tested against a single design, then produced nothing at all on the second, because it had quietly learned "navy" instead of "clothing".

deploy/nginx/ is version controlled. The client's production nginx config currently exists only on the server, hand-edited, with no history. Every config change here is a commit before it is a deployment — that is what makes rollback real rather than aspirational.

Setup

cp .env.example .env        # fill in; never commit
brew install gitleaks lefthook
lefthook install            # installs the pre-commit gate

The pre-commit hook runs gitleaks on staged content and blocks any new file over 10 MB. Both are there because this project has already seen a 664 env file holding live payment keys, and a 195 MB webroot. Neither belongs in git history, and history is permanent.

Workflow

Trunk-based. main is always deployable and protected; work happens on short-lived feat/ or fix/ branches merged by pull request, even when working alone — the PR is where the diff gets read as a whole.

Commits follow Conventional Commits (feat, fix, docs, refactor, test, chore, ops) and reference the vault in the body — Refs ADR-007, Closes S-01. That thread between decision record and implementation is what makes a cold reading possible in six months.

Every gate deliverable is tagged (gate-0, gate-1…). On a fixed-price contract with per-gate IP assignment, those tags are the contractual record of what was delivered and accepted on what date.

Deployment

Per ADR-007, release is a parallel-path cutover rather than an in-place overwrite:

python build.py --config templates/<name>.json --out dist/
rsync -avz --delete dist/ 3dct:/var/www/3dcaketopper.nl/configurator-next/
curl -I https://www.3dcaketopper.nl/configurator-next/      # verify before traffic
# cut over: one nginx location change, committed first
# roll back: revert that commit, nginx -s reload  (~10 seconds)

The existing /ontwerp/ configurator stays live and untouched throughout, which is what makes rollback instant.

Never edit files directly on the server. Commit, push, deploy.