# 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 ```bash 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: ```bash python build.py --config templates/.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.