Leander Christmann
Software Developer
4 of 42 projects shown. The rest is below.
Below the waterline
What is visible above is small. Underneath: the four projects hanging just under the surface, the technologies and ideas I work with, ordered from the lightly explored near the surface to the most deeply embedded in my work, the concrete work connecting them, and on the sea floor the old scars and abandoned attempts. Each item lists what it is connected to.
Projects
-
LCxHolz
An online shop for solid-wood goods made in my own workshop. Storefront and admin panel are written from scratch.
Connected to A shop, written not bought, CI/CD, Docker, Filament, Laravel, Livewire, MySQL, PHP, Playwright, Stripe.
visit → lcxholz.de -
Nusszopf
An archived open-source platform for ideas and projects, revived: four services became one Laravel app. The demo logs you in with one click.
Connected to CI/CD, Docker, Four services → one app, Laravel, Livewire, Meilisearch, PHP, Playwright, PostgreSQL.
Evidence: source.
visit → nusszopf.org -
Recipe Manager
A self-hosted recipe book for a family: cookbooks, a weekly planner, comments, image processing. Installs with Docker, and has a public demo.
Connected to Docker, Laravel, Livewire, Photos, but sensible, PostgreSQL.
Evidence: source.
visit → recipe-manager.de -
Romaji2Kana
Type Latin letters, get Japanese kana. A static site on S3 and CloudFront with a small Lambda API behind it.
Connected to 180 contract tests, AWS, CI/CD, JavaScript / TypeScript, Measured, then tuned, Node.js.
Evidence: source, API source.
visit → romaji2kana.com
Technologies
-
Codeception
the suite before the rewrite. The PHP acceptance-test framework the old suite was written in. Legacy, and the starting point of the rewrite.
Connected to Test-suite rewrite.
-
Grafana
explored. Dashboard tooling explored alongside building my own dashboards, including a small demo reading from two databases.
Connected to KPI dashboards.
Evidence: mysql-laravel-grafana-demo.
-
FinTS
talking to banks. The German banking protocol, spiked in isolation behind a recorded architectural decision. Exploratory.
Connected to A sync engine, written down.
-
Java
the university language. Where I learned to program properly: Maven, JUnit, Selenium, Spring Boot, a Lambda that parsed ML output. Rarely my first choice now.
Connected to Mobile & wearables, Sensor data for a prototype farm, Where it began.
-
Shell scripting
glue that ships. Installers with an upgrade path, deploy and backup scripts, container entrypoints.
Connected to A restore, actually tried, Automatic lab grading, Build once, install anywhere, Tools & automation.
-
InfluxDB
a time series, once. The database for a sensor-data prototype: written to from a Lambda, read by a dashboard.
Connected to Sensor data for a prototype farm.
-
ClickHouse
OLAP exploration. A column-store analytics database. Explored and integrated as the home for collected web-vitals metrics.
Connected to Collector and dashboard.
-
Image processing
pixels as a pipeline. Multi-size WebP pipelines in the recipe manager, and edge and line detection with OpenCV in a small crochet tool.
Connected to A grid for faint charts, Photos, but sensible.
Evidence: crochet-stitch-template-enhancer, answer: JPEG to WebP in PHP.
-
TYPO3
a CMS with a site package. Fluid templates, TypoScript and a custom site package, built as a reference site and worked with professionally.
Connected to Sites for people, Web apps & sites.
Evidence: simple-tailwind-site-typo3.
-
Android · Kotlin
where I started. Three Java apps in 2020, a Kotlin location tracker in 2025, and a minimal repro for a Stack Overflow question.
Connected to From one JSON file to many users, Mobile & wearables, Where it began.
Evidence: Tracker, android-octoquotes, WorkManager repro.
-
Offline-first sync
the network is optional. A local database, an outbox, idempotent replay and explicit conflict rules. In progress in a private finance planner.
Connected to A sync engine, written down.
-
Meilisearch
search as derived data. A fast search index that can be rebuilt from the database at any time, and whose hits are checked again before they are shown.
Connected to A disposable index, Nusszopf.
-
Stripe
taking real money. Checkout in a shop that handles real orders, with stock decremented in the same transaction as the order.
Connected to A shop, written not bought, LCxHolz, Never sell the last one twice.
-
Vue
single pages, when worth it. Used for client-heavy apps and maps: a recipe book, a tracker site, the offline-capable finance planner. Server-rendered Laravel is my default now.
Connected to A sync engine, written down, Four recipe books, From one JSON file to many users, Web apps & sites.
Evidence: recipe-app, tracker-website.
-
Application security
private means private. Policies instead of hope: private data that answers with a 404, multi-factor login, content-security policies, dependency audits and a secret scanner over the whole Git history.
Connected to A disposable index, Private means 404.
-
MySQL
the workhorse. The database behind the shop and much of what I touch at work, and a recurring character in demos and development setups.
Connected to A framework from scratch, LCxHolz, Never sell the last one twice.
-
Node.js
functions, pipes, tools. The runtime for Lambda functions, the Bitbucket pipe and small tools. A tool more than a home.
Connected to 180 contract tests, Custom Bitbucket Pipe, Romaji2Kana, Serverless hosting.
-
AWS
serverless and static hosting. S3 and CloudFront for hosting, Lambda for small APIs, scheduled jobs and edge functions, container images in ECR, event schedulers.
Connected to 180 contract tests, Browser automation in a Lambda, From one JSON file to many users, Measured, then tuned, Romaji2Kana, Sensor data for a prototype farm, Serverless hosting.
Evidence: answer: ECS container secrets.
-
WordPress
sites for people. Websites for people and organisations since 2020: a plugin, custom blocks, campaign pages, performance and security work. Real hands-on depth, in a world of its own.
Connected to Sites for people, Web apps & sites.
-
PostgreSQL
the single source of truth. The database under most of my recent self-hosted apps, with search indexes, caches and queues treated as derived data around it.
Connected to A disposable index, A sync engine, written down, Four services → one app, Nusszopf, Recipe Manager.
-
Pest · PHPUnit
tests against the real thing. Feature and unit suites against a real database, with static analysis and code style enforced in CI. I also wrote a script that converts PHPUnit’s report format.
Connected to A converter for broken reports, Check everything on push, Never sell the last one twice.
Evidence: make-phpunit-report-standard-junit-xml, mysql-laravel-grafana-demo.
-
Spec-first documentation
write the product down first. Requirements, design, architecture and implementation as separate documents; decision records, bug registers, golden masters. A habit that shows in nearly every recent repository.
Connected to A product as a golden master, A sync engine, written down, KPI dashboards, Looks the same as before.
Evidence: waffle-dashboard.
-
Rendering patterns
where a pixel comes from. Static, server and client rendering, hydration, and what each does to the browser’s work. The theory beneath the vitals, tried in a thesis case study.
Connected to Thesis on rendering, Three pages, three fixes.
Evidence: store (thesis case study), answer: what “rendering” means.
-
Self-hosting
own the whole stack. Open-source apps I run myself, and apps I write so that others can: a VPS, a reverse proxy, backups that were restored once, analytics without a SaaS bill.
Connected to A cloud for student councils, A restore, actually tried, Build once, install anywhere, From one JSON file to many users, Self-hostable apps.
Evidence: selfhosted-tracker-backend, waffle-dashboard.
-
Docker
install with a few commands. Everything I build ships as containers. My self-hostable apps need a server with Docker and nothing else, from the development setup to multi-architecture production images.
Connected to A cloud for student councils, A grid for faint charts, Browser automation in a Lambda, Build once, install anywhere, Check everything on push, LCxHolz, Nusszopf, Photos, but sensible, Recipe Manager, Self-hostable apps, Sites for people.
-
CI/CD
build · lint · test · ship. Pipelines that build, check and test every push: GitHub Actions, GitLab CI and Bitbucket. Smoke tests run against the real production images, and releases are gated on the full suite.
Connected to A converter for broken reports, Automatic lab grading, Build once, install anywhere, Check everything on push, Custom Bitbucket Pipe, LCxHolz, Nusszopf, Romaji2Kana, Serverless hosting, Test-suite rewrite, Tools & automation.
-
JavaScript / TypeScript
both ends of the wire. Browser logic, Lambda functions, the Bitbucket pipe, Playwright suites and a full TypeScript monorepo. What I automate everything else with.
Connected to 180 contract tests, A sync engine, written down, Collector and dashboard, Cross-browser E2E, Romaji2Kana.
Evidence: romaji2kana-api.
-
Bitbucket Pipelines
a custom pipe, still maintained. Pipelines are where my team’s code gets checked and shipped. I wrote a reusable pipe on Node.js and still maintain it. Also a recurring topic of my Stack Overflow answers.
Connected to Custom Bitbucket Pipe, Tools & automation.
Evidence: answer: variables across steps.
-
Livewire
interactivity without an SPA. Server-rendered interactive pages for the shop, the recipe manager and Nusszopf, and the engine underneath Filament.
Connected to A shop, written not bought, Four recipe books, Four services → one app, LCxHolz, Nusszopf, Recipe Manager.
Evidence: recipe-manager, nusszopf.
-
Filament
dashboards and admin panels. The tool for KPI dashboards and admin panels on Laravel, used daily: roles, widgets, live-edit tables, multi-factor login. It also runs a deeply serious waffle leaderboard.
Connected to A shop, written not bought, KPI dashboards, LCxHolz, Mission aborted.
Evidence: waffle-dashboard, simple-music-manager.
-
Core Web Vitals
measurement → metrics → dashboard. The subject of my bachelor’s thesis, later a talk, a collector and a dashboard in practice. One of the areas I understand best, from how a browser renders to how to measure it.
Connected to Collector and dashboard, Measured, then tuned, Thesis on rendering, Three pages, three fixes.
Evidence: core-web-vitals-lcp-demo, core-web-vitals-cls-demo, core-web-vitals-inp-demo.
-
Playwright
complete test-suite rewrite. The strongest current testing tool in my hands: a whole suite rewritten from Codeception, and cross-browser suites with accessibility and visual checks in my own projects.
Connected to A product as a golden master, A sync engine, written down, Check everything on push, Cross-browser E2E, LCxHolz, Looks the same as before, Nusszopf, Test-suite rewrite.
Evidence: nusszopf.
-
Laravel
application architecture. Server-rendered monoliths I own end to end: a shop, a recipe book, an ideas platform, an API, dashboards. Policies, queues, schedulers, migrations.
Connected to A disposable index, A product as a golden master, A restore, actually tried, A shop, written not bought, Four recipe books, Four services → one app, From one JSON file to many users, KPI dashboards, LCxHolz, Mission aborted, Never sell the last one twice, Nusszopf, Photos, but sensible, Private means 404, Recipe Manager, Self-hostable apps, Web apps & sites.
Evidence: nusszopf, recipe-manager, waffle-dashboard, selfhosted-tracker-backend.
-
PHP
the language I come back to. From a first form-to-spreadsheet script, through a hand-built MVC framework, to typed modern PHP in every server-side project since. Static analysis at level 7, tests on every push.
Connected to A cloud for student councils, A converter for broken reports, A framework from scratch, LCxHolz, Nusszopf, Sites for people, Web apps & sites.
Work
-
Test-suite rewrite
The whole suite moved from Codeception to Playwright, not a showcase subset, and got better on the way.
Connected to CI/CD, Codeception, Playwright.
-
Cross-browser E2E
Chromium, Firefox, WebKit, emulated phones and a tablet, with axe accessibility checks.
Connected to JavaScript / TypeScript, Playwright.
-
Looks the same as before
Screenshot regression over 23 pages at three widths: the promise of a revival is that nothing visibly changed.
Connected to Playwright, Spec-first documentation.
-
A product as a golden master
Before any code, the archived original was written down as a specification. A bug register of 47 entries classifies each defect as fix, preserve, replace or unknown, and a fix needs its regression test written first.
Connected to Laravel, Playwright, Private means 404, Spec-first documentation.
Evidence: nusszopf.
-
Check everything on push
Static analysis, unit tests and Playwright runs, plus a smoke test that builds the production images and checks they come up healthy.
Connected to CI/CD, Docker, Pest · PHPUnit, Playwright.
-
Custom Bitbucket Pipe
A reusable pipeline step based on Node.js. Created and still maintained.
Connected to Bitbucket Pipelines, CI/CD, Node.js, Tools & automation.
-
Automatic lab grading
CI pipelines that test students’ code against the professor’s tests, with a live results dashboard published from the pipeline itself.
Connected to CI/CD, Shell scripting, Tools & automation.
-
Build once, install anywhere
A version tag runs the full CI as a gate, then builds multi-architecture images. An operator downloads install.sh and runs one command. The first release candidate could not install itself: GitHub drops release assets whose names start with a dot.
Connected to CI/CD, Docker, Self-hosting, Shell scripting.
Evidence: nusszopf.
-
A converter for broken reports
A small PHP script that turns PHPUnit’s non-standard JUnit XML into standard JUnit XML.
Connected to CI/CD, Pest · PHPUnit, PHP, Tools & automation.
Evidence: make-phpunit-report-standard-junit-xml.
-
Thesis on rendering
Rendering patterns and their effect on Core Web Vitals, with a case study: a store where each page uses the pattern that fits it, and a comparison of what a careless choice costs.
Connected to Core Web Vitals, Rendering patterns, Three pages, three fixes.
Evidence: store (case study).
-
Three pages, three fixes
A talk on how the browser works and how to measure vitals, with one demo each showing how to fix an LCP, a CLS and an INP problem.
Connected to Collector and dashboard, Core Web Vitals, Rendering patterns, Thesis on rendering.
-
Collector and dashboard
A way to collect web-vitals data from real pages, keep it in ClickHouse and look at it in a demo dashboard.
Connected to ClickHouse, Core Web Vitals, JavaScript / TypeScript, Three pages, three fixes.
-
Measured, then tuned
Lighthouse before and after on Romaji2Kana: performance 99 → 100, accessibility 82 → 100, SEO 83 → 92, total blocking time 90 → 20 ms.
Connected to AWS, Core Web Vitals, Romaji2Kana.
-
180 contract tests
A Lambda API with an Express twin for local work, and a Postman suite of 180+ tests that also validates the JSON schema of every response.
Connected to AWS, JavaScript / TypeScript, Node.js, Romaji2Kana.
Evidence: romaji2kana-api.
-
KPI dashboards
Analytics and admin dashboards on Filament, including a live-edit goals planner and a waffle leaderboard that took its requirements very seriously.
Connected to Filament, Grafana, Laravel, Spec-first documentation.
Evidence: waffle-dashboard.
-
Four services → one app
Nusszopf kept its look and behaviour but moved from four services across three hosts into a single Laravel application: seven containers, one install script.
Connected to Laravel, Livewire, Nusszopf, PostgreSQL.
-
A shop, written not bought
Storefront, cart, stock, Stripe checkout and an admin panel, built from scratch for a real business. German shop law included: invoices, withdrawal and complaint flows, statutory retention.
Connected to Filament, Laravel, LCxHolz, Livewire, Stripe.
-
Never sell the last one twice
Stock is decremented in the same transaction that creates the order, orders snapshot prices and addresses, and everything after checkout reads the snapshot. A real bug taught the last rule: totals recomputed from live stock.
Connected to Laravel, MySQL, Pest · PHPUnit, Stripe.
-
A disposable index
The search index is derived data: one command rebuilds it from PostgreSQL, and hits are re-checked against the database so a project that turned private disappears at once.
Connected to Application security, Laravel, Meilisearch, PostgreSQL.
-
Private means 404
Policies replaced the old permission rules, and the rewrite found that the original leaked the entries of private projects. A private project now answers everyone but its owner with a 404, even on the direct link.
Connected to A product as a golden master, Application security, Laravel.
-
Photos, but sensible
Uploads are scaled, converted to WebP in several sizes, permission-checked by the app and then handed to Nginx with X-Accel-Redirect. Scheduled jobs delete orphaned folders.
Connected to Docker, Image processing, Laravel, Recipe Manager.
-
Self-hostable apps
Recipe book, ideas platform, tracker backend, waffle dashboard, music manager: each ships as Docker images with an install guide.
Connected to Docker, Laravel, Self-hosting.
Evidence: selfhosted-tracker-backend, simple-music-manager, waffle-dashboard.
-
A restore, actually tried
Backups are scheduled in the app, and the restore procedure was run end to end once while building it, instead of trusting the documentation.
Connected to Laravel, Self-hosting, Shell scripting.
-
Browser automation in a Lambda
A containerised Selenium script on AWS Lambda, started daily by a scheduler, to earn a gold badge. Not forbidden, per Stack Overflow’s own meta discussion.
Connected to AWS, Docker, Tools & automation.
Evidence: aws-lambda-function-for-stackoverflow-fanatic-badge.
-
Serverless hosting
Static sites on S3 and CloudFront, with edge functions for authentication and URL rewriting once the bucket became private.
Connected to AWS, CI/CD, Node.js.
-
From one JSON file to many users
A location tracker: a Kotlin app, a Lambda API appending to a file on S3, a map site. When others wanted in, the API was rebuilt as a self-hostable Laravel backend, without the secret baked into the app.
Connected to Android · Kotlin, AWS, Laravel, Mobile & wearables, Self-hosting, Vue.
Evidence: Tracker, tracker-api-aws-lambda-function, selfhosted-tracker-backend.
-
A grid for faint charts
A Python and OpenCV tool that detects the faint lines of a crochet chart and overlays a clean grid. One Docker command, no editing by hand.
Connected to Docker, Image processing, Tools & automation.
Evidence: crochet-stitch-template-enhancer.
-
A sync engine, written down
Client-generated IDs, an outbox, an idempotency ledger and field-level last-write-wins with a conflict log, argued in decision records first. Offline editing is covered by an end-to-end test. In progress.
Connected to FinTS, JavaScript / TypeScript, Offline-first sync, Playwright, PostgreSQL, Spec-first documentation, Vue.
-
Sites for people
WordPress sites with caching and security plugins, custom blocks and a live countdown, a form-to-spreadsheet plugin, and Dockerised side tools for an organisation.
Connected to Docker, PHP, TYPO3, WordPress.
Evidence: simple-tailwind-site-typo3.
-
Mobile & wearables
7 apps and attempts. Three Android apps released in 2020–21, a Wear OS watch face, a Kotlin location tracker with its own backend, and two attempts at a cross-platform music manager. A whole mobile history, almost all of it below the surface.
Connected to Android · Kotlin, From one JSON file to many users, Java, Mission aborted, Where it began.
Evidence: android-octoquotes, android-flyleaf, android-dirtywork, Tracker.
-
Web apps & sites
22 apps, sites and demos. Recipe books, dashboards, a thesis store, landing pages, CMS sites, a self-hosted collaboration stack, a hand-made PHP framework. Most stayed small; a few kept growing until they became the pinnacles above.
Connected to A cloud for student councils, A framework from scratch, Four recipe books, Laravel, PHP, TYPO3, Vue, WordPress.
Evidence: waffle-dashboard, simple-music-manager, store, simple-tailwind-site-vue.
-
Tools & automation
9 small tools. Built because nothing suited: a pipeline step, a report converter, a privacy-audit browser extension, a Lambda that earns a badge, a grid detector for crochet charts, grading pipelines, a word clock.
Connected to A clock that spells the time, A converter for broken reports, A grid for faint charts, Automatic lab grading, Bitbucket Pipelines, Browser automation in a Lambda, CI/CD, Custom Bitbucket Pipe, Shell scripting.
Evidence: aws-lambda-function-for-stackoverflow-fanatic-badge, crochet-stitch-template-enhancer, make-phpunit-report-standard-junit-xml, lexia.
Stack Overflow
- answers
- 51
- accepted
- 12
- reputation
- 1,031
- badges
- 2 gold, 12 silver, 28 bronze
- Gradient text in Tailwind CSS
- Variables across Bitbucket pipeline steps
- Updating ECS container secrets
- JPEG to WebP in PHP
- What “rendering” means on the web
as of 2026-10-05
On the sea floor
-
Where it began
Three Android apps in Java: a to-do list, a books app and a quotes app with 2,000 citations. Where programming started.
Connected to Android · Kotlin, Java, Mobile & wearables.
Evidence: android-octoquotes.
-
Mission aborted
A music manager for mobile, attempted in NativePHP, then again offline-first in Flutter, and in the end not built as a mobile app at all. The plain web app won, and shipped.
Connected to Filament, Laravel, Mobile & wearables.
Evidence: simple-music-manager.
-
Four recipe books
A Vue app for myself; a Vue and Inertia rewrite, abandoned; a plan with an admin backend, never done; and the Livewire version that stuck.
Connected to Laravel, Livewire, Vue, Web apps & sites.
Evidence: recipe-app, recipe-manager.
-
A framework from scratch
A small PHP MVC framework with a Docker Compose setup, written to understand what frameworks do before relying on one.
Connected to MySQL, PHP, Web apps & sites.
-
A cloud for student councils
A self-hosted suite of file storage, chat, video calls and a directory service, glued by a custom portal. LDAP, a CodeIgniter app and an architecture document I was in charge of.
Connected to Docker, PHP, Self-hosting, Web apps & sites.
Evidence: demo-lamp-stack-with-ldap.
-
Sensor data for a prototype farm
A Lambda in Java that parsed an image-recognition model’s output into InfluxDB, a PHP dashboard to read it, and the same dashboard wrapped as Android and iOS apps.
Connected to AWS, InfluxDB, Java.
-
A clock that spells the time
Firmware for self-made word clocks, in C++ on an Arduino. No server involved.
Connected to Tools & automation.