← werkstatt

Webdev.

AtelierCMS, Zeiterfassung, the alpineminds site. Things that ship.

Self-hosted web apps for Swiss contexts. PHP where it makes sense, Astro where it shines. No framework churn — just tools that stay out of the way.

2026-04-10

AtelierCMS: drag-to-reorder gallery without a JS framework

Implemented drag-and-drop image ordering in the CMS admin using the HTML5 Drag and Drop API. No Sortable.js, no React. Saves order to a JSON sidecar file.

2026-04-01

AtelierCMS: asset pipeline fix — images were being served unoptimised

Discovered that AtelierCMS was serving original uploads directly. Added a simple on-demand resize pipeline. 80% size reduction on average.

2026-03-22

AlpineTime: frontend — Vue 3, composables, i18n from day one

Vue 3 + TypeScript + PrimeVue. Silent token refresh, error codes mapped to i18n keys, composables keeping pages under 100 lines. German UI from the first component.

2026-03-21

AlpineTime: backend — FastAPI, async ORM, rate resolution

FastAPI with SQLAlchemy 2.0 async. The interesting parts: overlap detection with user-driven resolution, rate snapshotting, and MWST applied at report total rather than per line.

2026-03-19

AlpineTime: what the spec went through before touching code

Seven versions of the spec before the first commit. The Swiss constraints — MWST, nDSG, Europe/Zurich, German UI — decided most of the architecture before any code was written.

2026-03-14

AtelierCMS: multilingual routing without a framework

Added DE/FR/IT language switching to AtelierCMS using path prefixes and a dead-simple URL rewrite. No i18n library needed.

2026-01-09

Zeiterfassung: CSV export that accounting could actually open

The CSV export worked. Excel couldn't open it. The fix was two lines and deeply annoying.