[
  {
    "id": 105,
    "date": "2026-04-29",
    "bench": "homelab",
    "title": "My Homelab Journey until 2026",
    "summary": "Have my own infrastructure for my tech needs. For privacy, learning and convinience",
    "tags": [
      "homelab",
      "storage",
      "selfhosting"
    ],
    "url": "https://meica.ch/werkstatt/homelab/why-i-started-my-homelab"
  },
  {
    "id": 101,
    "date": "2026-04-23",
    "bench": "homelab",
    "title": "k3s 1.29.3 upgrade — zero downtime, eventually",
    "summary": "Rolling k3s from 1.28.x to 1.29.3 on a three-node cluster with live workloads. Ceph made it interesting.",
    "tags": [
      "kubernetes",
      "k3s",
      "upgrade",
      "ceph",
      "traefik"
    ],
    "url": "https://meica.ch/werkstatt/homelab/k3s-1-29-3-upgrade"
  },
  {
    "id": 113,
    "date": "2026-04-18",
    "bench": "fpv",
    "title": "5\" freestyle: HQ 5x4.3x3 vs. Gemfan 51433 — alpine conditions",
    "summary": "Ran both props back to back on the same tune in the same field. HQ wins in wind. Gemfan has better punch in calm air. I'm keeping HQs on this build.",
    "tags": [
      "fpv",
      "betaflight"
    ],
    "url": "https://meica.ch/werkstatt/fpv/5inch-freestyle/props-comparison"
  },
  {
    "id": 104,
    "date": "2026-04-18",
    "bench": "gamedev",
    "title": "Terrain chunks + LOD rings — from framerate disaster to playable",
    "summary": "The terrain generator worked. It generated 50,000 triangles per chunk at full detail. LOD rings cut that to 3,000 at distance. Now it runs.",
    "tags": [
      "godot",
      "procgen",
      "terrain",
      "lod",
      "performance"
    ],
    "url": "https://meica.ch/werkstatt/gamedev/terrain-chunks-lod"
  },
  {
    "id": 102,
    "date": "2026-04-12",
    "bench": "fpv",
    "title": "Piz Beverin — 3.4km out, returned",
    "summary": "3.4km out-and-back over the Beverin, 680m of altitude gain, no signal loss. The mountains are the best antenna range test there is.",
    "tags": [
      "fpv",
      "longrange",
      "mountains",
      "graubünden"
    ],
    "url": "https://meica.ch/werkstatt/fpv/piz-beverin"
  },
  {
    "id": 111,
    "date": "2026-04-10",
    "bench": "webdev",
    "title": "AtelierCMS: drag-to-reorder gallery without a JS framework",
    "summary": "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.",
    "tags": [
      "php",
      "cms",
      "images"
    ],
    "url": "https://meica.ch/werkstatt/webdev/ateliercms/gallery-ordering"
  },
  {
    "id": 116,
    "date": "2026-04-05",
    "bench": "gamedev",
    "title": "Roguelike #3: FOV with recursive shadowcasting",
    "summary": "Implemented recursive shadowcasting for field of view. The algorithm is elegant once you understand the octant recursion. Getting it right took three attempts.",
    "tags": [
      "godot",
      "roguelike",
      "algorithms"
    ],
    "url": "https://meica.ch/werkstatt/gamedev/roguelike-3/fov-shadowcasting"
  },
  {
    "id": 103,
    "date": "2026-04-01",
    "bench": "webdev",
    "title": "AtelierCMS: asset pipeline fix — images were being served unoptimised",
    "summary": "Discovered that AtelierCMS was serving original uploads directly. Added a simple on-demand resize pipeline. 80% size reduction on average.",
    "tags": [
      "php",
      "cms",
      "images",
      "performance",
      "atelier"
    ],
    "url": "https://meica.ch/werkstatt/webdev/ateliercms-asset-pipeline"
  },
  {
    "id": 100,
    "date": "2026-03-28",
    "bench": "fpv",
    "title": "New 2207 motors on the 5\" long range — quieter, more efficient",
    "summary": "Swapped to 1750kV 2207s on the long-range 5\". Gained 4 minutes of flight time. Lost the characteristic scream. Worth it.",
    "tags": [
      "fpv",
      "motors",
      "5inch",
      "longrange",
      "efficiency"
    ],
    "url": "https://meica.ch/werkstatt/fpv/2207-motors-long-range"
  },
  {
    "id": 112,
    "date": "2026-03-28",
    "bench": "fpv",
    "title": "5\" freestyle: PID retune after frame swap",
    "summary": "Swapped to a stiffer carbon frame after a crack in the old one. Had to retune from scratch — the resonance profile was completely different.",
    "tags": [
      "fpv",
      "betaflight",
      "blackbox"
    ],
    "url": "https://meica.ch/werkstatt/fpv/5inch-freestyle/pid-tune-spring-2026"
  },
  {
    "id": 119,
    "date": "2026-03-22",
    "bench": "webdev",
    "title": "AlpineTime: frontend — Vue 3, composables, i18n from day one",
    "summary": "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.",
    "tags": [
      "vue",
      "typescript",
      "swiss"
    ],
    "url": "https://meica.ch/werkstatt/webdev/alpinetime/frontend"
  },
  {
    "id": 118,
    "date": "2026-03-21",
    "bench": "webdev",
    "title": "AlpineTime: backend — FastAPI, async ORM, rate resolution",
    "summary": "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.",
    "tags": [
      "fastapi",
      "python",
      "swiss",
      "selfhosted"
    ],
    "url": "https://meica.ch/werkstatt/webdev/alpinetime/backend"
  },
  {
    "id": 99,
    "date": "2026-03-20",
    "bench": "local-ai",
    "title": "Mistral 7B Q4_K_M running local — notes from the first week",
    "summary": "Running Mistral 7B Q4_K_M via llama.cpp on a Mac Mini M2. Fast enough for daily use. Notes on what works, what doesn't, and what I actually use it for.",
    "tags": [
      "llm",
      "mistral",
      "llama.cpp",
      "local-ai",
      "hardware"
    ],
    "url": "https://meica.ch/werkstatt/local-ai/mistral-7b-local"
  },
  {
    "id": 117,
    "date": "2026-03-19",
    "bench": "webdev",
    "title": "AlpineTime: what the spec went through before touching code",
    "summary": "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.",
    "tags": [
      "fastapi",
      "vue",
      "swiss"
    ],
    "url": "https://meica.ch/werkstatt/webdev/alpinetime/planning"
  },
  {
    "id": 110,
    "date": "2026-03-14",
    "bench": "webdev",
    "title": "AtelierCMS: multilingual routing without a framework",
    "summary": "Added DE/FR/IT language switching to AtelierCMS using path prefixes and a dead-simple URL rewrite. No i18n library needed.",
    "tags": [
      "php",
      "cms",
      "swiss"
    ],
    "url": "https://meica.ch/werkstatt/webdev/ateliercms/multilingual-routing"
  },
  {
    "id": 115,
    "date": "2026-03-05",
    "bench": "fpv",
    "title": "Long range wing: tuning GPS rescue for mountain terrain",
    "summary": "Default GPS rescue parameters are tuned for flat terrain. In a valley with ridges on three sides, they'll fly you into a hillside. Notes on what to change.",
    "tags": [
      "fpv",
      "longrange",
      "rc"
    ],
    "url": "https://meica.ch/werkstatt/fpv/long-range-wing/gps-rescue-tuning"
  },
  {
    "id": 97,
    "date": "2026-03-05",
    "bench": "making",
    "title": "Swiss-DE names on ESP32 e-ink — Umlauts, Waveshare, and a three-day font problem",
    "summary": "Displaying Swiss-German municipality names on a Waveshare e-ink display. The names contain umlauts. The default font doesn't. Three days later.",
    "tags": [
      "esp32",
      "e-ink",
      "making",
      "fonts",
      "swiss",
      "embedded"
    ],
    "url": "https://meica.ch/werkstatt/making/swiss-de-esp32-eink"
  },
  {
    "id": 95,
    "date": "2026-02-22",
    "bench": "gamedev",
    "title": "Roguelike: line-of-sight rewrite",
    "summary": "Replaced the naive raycasting LOS with symmetric shadowcasting. Faster, correct at corners, and the symmetry property turns out to matter for gameplay.",
    "tags": [
      "godot",
      "roguelike",
      "algorithms",
      "los"
    ],
    "url": "https://meica.ch/werkstatt/gamedev/roguelike-los-rewrite"
  },
  {
    "id": 94,
    "date": "2026-02-14",
    "bench": "homelab",
    "title": "OPNsense + WireGuard road-warrior — config that actually works",
    "summary": "WireGuard road-warrior setup on OPNsense with split tunneling and a working kill switch. Third attempt was the one that stuck.",
    "tags": [
      "opnsense",
      "wireguard",
      "vpn",
      "network",
      "road-warrior"
    ],
    "url": "https://meica.ch/werkstatt/homelab/opnsense-wireguard"
  },
  {
    "id": 114,
    "date": "2026-02-10",
    "bench": "fpv",
    "title": "Long range wing: ExpressLRS 868MHz setup and binding",
    "summary": "First flight on ELRS 868MHz. Replaced a 2.4GHz Crossfire setup — better penetration in the canyon sections, same telemetry quality.",
    "tags": [
      "fpv",
      "longrange",
      "rc"
    ],
    "url": "https://meica.ch/werkstatt/fpv/long-range-wing/elrs-initial-setup"
  },
  {
    "id": 91,
    "date": "2026-01-28",
    "bench": "making",
    "title": "Solder fume extractor — first burn, design notes",
    "summary": "Built a small fume extractor from a PC fan, activated carbon filter, and 3D-printed housing. Works. Loud. Will iterate.",
    "tags": [
      "making",
      "soldering",
      "tools",
      "3d-printing"
    ],
    "url": "https://meica.ch/werkstatt/making/solder-fume-extractor"
  },
  {
    "id": 90,
    "date": "2026-01-15",
    "bench": "local-ai",
    "title": "LiteLLM proxy — one endpoint, rotated keys",
    "summary": "LiteLLM proxy sitting in front of multiple LLM backends. Key rotation without touching application config. Worth it.",
    "tags": [
      "litellm",
      "llm",
      "proxy",
      "agentic",
      "local-ai"
    ],
    "url": "https://meica.ch/werkstatt/local-ai/litellm-proxy-keys"
  },
  {
    "id": 89,
    "date": "2026-01-09",
    "bench": "webdev",
    "title": "Zeiterfassung: CSV export that accounting could actually open",
    "summary": "The CSV export worked. Excel couldn't open it. The fix was two lines and deeply annoying.",
    "tags": [
      "vue",
      "csv",
      "encoding",
      "excel"
    ],
    "url": "https://meica.ch/werkstatt/webdev/zeiterfassung-csv-export"
  }
]