Projects

What I've put to sea so far, what it was built from, and who it was for.

bearing weight, share of the workmost of itpart of itin passing

cct

06 sheets, 2020 to 2026

The student consultancy at TU Berlin, where I have been a member since 2024. Its internal tools, the machines they run on, and its public site.

Member portal for a student consultancyweb2020 to 2026
source privatecct series, sheet 01 of 06

Members, projects, events, documents and finance requests in one internal app, running since 2020 and rebuilt on a newer frontend along the way. I work both ends of it: attendance statistics, a slide export service, scheduled jobs, and the pipeline that ships the whole thing.

most of it
Vue 3PythonFastAPI
part of it
TypeScriptPostgreSQLGitLab CI
in passing
CeleryDocker
Website for a student IT consultancyweb2025 to 2026
source privatecct series, sheet 02 of 06

Public pages plus server routes behind three forms: contact, application and a coffee chat. Schema validation, rate limiting, a CAPTCHA check, a honeypot and mail out over SMTP. Lead developer, from the architecture to the image the pipeline deploys.

most of it
AstroTypeScript
part of it
Tailwind CSSZodNode.jsGitLab CI
in passing
NginxDocker
The site at juniter.de as it looked on 2026-09-06
juniter.desurveyed 2026-09-06
Slack bot that relays and tracks ticketsweb2024 to 2026
source privatecct series, sheet 03 of 06

Forwards messages into private channels and turns them into support tickets, with modals, reactions, a home tab and a slash command. Started by others in 2019; every commit since late 2024 is mine, including the third rewrite and the deploy it rides on.

most of it
PythonFlaskSlack API
part of it
SQLiteGitLab CI
in passing
Docker Swarm
Who is in the room, read off the WiFiweb2025
source privatecct series, sheet 04 of 06

Asks the router which devices are on the WiFi and answers the one question anyone walking over actually has: is somebody up there. I took over an existing app to containerise the deploy, redesign the page and make presence detection stop lying.

most of it
PythonJinja2
part of it
FastAPIDockerCaddy
in passing
Pydantic
The site at tower.cct-ev.de as it looked on 2026-09-06
tower.cct-ev.desurveyed 2026-09-06
Self-hosted web analyticsinfra2026
source privatecct series, sheet 05 of 06

Traffic figures on our own hardware, so visitors are counted without being handed to a tracker. The app is upstream and untouched; mine is everything under it, from the database and the certificates to the tagged release that puts it live.

most of it
Docker SwarmBashGitLab CI
part of it
PostgreSQLTraefik
in passing
UmamiLet's Encrypt
Self-hosted CAPTCHA serviceinfra2026
source privatecct series, sheet 06 of 06

An open-source CAPTCHA run on our own machine instead of handed to a third party, so the forms it guards leak nothing to anyone. All infrastructure: a Swarm stack behind a reverse proxy with certificates that renew themselves, shipped by tag.

most of it
Docker SwarmBashGitLab CI
part of it
Traefik
in passing
Let's Encrypt
own

Own account

08 sheets, 2024 to 2026

Built for myself and run on my own machines. The source is public wherever it is not personal.

Prediction markets on Solanaweb32025
delphimarketsio/delphimarketsioown series, sheet 01 of 08

Yes/no markets anyone can open from a link, stake SOL on and settle on-chain. Anchor program, Vue frontend, and the pipelines that build, test and deploy both.

most of it
RustAnchorVue 3TypeScript
part of it
SolanaGitHub Actions
in passing
PlaywrightNginx
This site: chart paper, then deep waterweb2026
marcel290820/about-meown series, sheet 02 of 08

The page you are on. Ink on paper above the fold, open water below it, and a scroll that reads as a descent. Content is markdown in typed collections, search is indexed in the pipeline, and every figure in the water column is sampled from one curve library rather than drawn by hand.

most of it
AstroTailwind CSSSVG
part of it
TypeScriptMDXZod
in passing
GitHub ActionsGitHub Pages
live →
One command to rebuild a Macinfra2024 to 2026
marcel290820/configown series, sheet 03 of 08

Dotfiles, packages and tool configuration in one repository behind one idempotent script. Symlinks round edits back into the repo instead of letting it drift, templates take their secrets from the environment, and anything it replaces is backed up first. Re-running it is the normal case, not the recovery case.

most of it
Bash
part of it
macOSZshtmux
in passing
HomebrewNeovimGit
A CV that compiles, one PDF per applicationinfra2026
source privateown series, sheet 04 of 08

Content in YAML, layout in Typst, and a thin file per application that overrides only the fields a role needs. The build deep-merges a variant over the base and compiles it, so tailoring a CV is a few lines rather than a copy that will go stale. Motivation letters run through the same split.

most of it
TypstYAML
part of it
BashPython
in passing
Git
Two morning digests and an hourly watchdata2026
marcel290820/daily-digestown series, sheet 05 of 08

Reads Hacker News and two news feeds, folds in two fear-and-greed indices, and puts a digest in Telegram before breakfast. Three timers, one SQLite file, no auth and no containers. It is one Python package on a small Linux box, and that is the whole design.

most of it
Python
part of it
TelegramSQLitePytest
in passing
LinuxBash
Git worktrees, one command per featureinfra2025 to 2026
marcel290820/git-toolkitown series, sheet 06 of 08

Branches, creates a worktree beside the repository rather than inside it, and opens each one in its own editor window. Names are sanitised on the way in, the base branch is a flag, and several features can be set up in a single call.

most of it
Bash
part of it
Git
in passing
macOS
A depot that says when it has drifteddata2026
marcel290820/investment-toolsown series, sheet 07 of 08

Reads a brokerage depot, compares it against a target allocation, and names only the positions that have wandered far enough to be worth acting on. It reads and never writes: no order passes through it, and the suggestion is always where to put new money, never what to sell. Every check is stored, so the report can say how long a position has been out of band.

most of it
Python
part of it
TelegramSQLitePytest
in passing
LinuxRuff
Count a document's tokens before you send itdata2026
marcel290820/llm-toolsown series, sheet 08 of 08

Pulls the text out of a PDF and counts it with the same tokenizer the model uses, so you know whether it fits before you paste it. Picks the encoding from a model name, and prints either per-file detail or a single number for a script to read.

most of it
Python
part of it
Bash
in passing
Linux
crest withheld
client

Under contract

03 sheets, 2025 to 2026

Work for companies that stay unnamed here. The sheets say what was built, not for whom.

Multi-app platform for a stealth startupweb32026
source privateclient series, sheet 01 of 03

Four Next.js apps on one Fastify backend, with Postgres holding the records and ClickHouse the analytics read off them. Collectors on their own boxes feed on-chain, market and social data in, deployed from the repo by Ansible so a machine is never edited by hand. I worked across all of it, front to back, from the query layer to the boxes.

most of it
Next.jsReactFastify
part of it
DrizzlePostgreSQLClickHouse
in passing
RedisAnsible
Four routes out of a time-series bottleneckdata2025
source privateclient series, sheet 02 of 03

The log and measurement tables under a water-industry platform had outgrown the database holding them. I benchmarked native Postgres partitioning, TimescaleDB and Citus against a seven-million-row production extract and generated multi-tenant data, priced vertical scaling beside them, and wrote the recommendation with the numbers that led to it.

most of it
PostgreSQLTimescale
part of it
OpenJDKJUnitDockerBash
in passing
DBeaverHetzner
Sickness risk read off a phone's health datamobile2026
source privateclient series, sheet 03 of 03

An iOS app that reads Apple Health and scores the day's sickness risk against a model in the cloud. My work was the score and the data under it: one definition of it pinned by a replay fixture, recalibrated once measurement showed it sitting below chance, and made to hold up on a device with signals missing. Underneath, a raw lake reconciled against the warehouse before anything was trimmed, with retention and deletion enforced by the job rather than by hand.

most of it
SwiftPython
part of it
FirebaseGoogle CloudBigQueryPytest
in passing
XcodeApple
tu berlin

05 sheets, 2023 to 2026

Coursework and both theses from the industrial engineering and IT degrees, bachelor and master.

Forecasting German house pricesdata2023
source privatetu berlin series, sheet 01 of 05

A bachelor thesis on predicting residential sale prices from a national real-estate dataset joined to socio-economic and demographic data. Gradient-boosted trees against a neural baseline, trained separately on the years around the crisis and the years without it, and read back with Shapley values rather than an error figure alone.

most of it
PythonJupyterLaTeX
part of it
pandasscikit-learn
in passing
NumPy
Teaching an agent to spend fewer tokensdata2026
marcel-tu-berlin/master-thesis-codetu berlin series, sheet 02 of 05

A master thesis on reward shaping in GRPO: a cosine length reward and a penalty for never stopping, applied to a tool-calling policy trained against live environments instead of a graded answer string. Experiments are configuration rather than code, and every measurement is pinned by a test, because a silent change to how tokens are counted quietly invalidates runs that cost GPU hours.

most of it
PythonHugging Face
part of it
PyTorchQwenLinuxPytest
in passing
NVIDIAuv
Eleven network labs, from fat-tree to QUICinfra2025 to 2026
source privatetu berlin series, sheet 03 of 05

A term of protocol assignments built rather than answered: emulated data-centre topologies with a learning switch on a software-defined network, queueing simulations, message-passing benchmarks across hosts, crafted packet captures, and a QUIC client and server written against the protocol's own stream semantics. Each one written up as a paper.

most of it
Python
part of it
LinuxCLaTeX
in passing
Bash
Numerics, from a draining reservoir to flowdata2025 to 2026
source privatetu berlin series, sheet 04 of 05

Engineering computation in Python: a two-dimensional lattice-Boltzmann simulation of flow past an obstacle, a reservoir emptied one time step at a time, and cycling counts regressed against Berlin weather. Graded automatically against hidden assertions, so the numbers had to come out right, not merely look right.

most of it
PythonNumPyJupyter
part of it
pandas
in passing
SciPy
Finding the duplicates in a software estatedata2024 to 2025
source privatetu berlin series, sheet 05 of 05

Matching an organisation's software inventory against a catalogue of thousands of tools to show where it is paying twice for one capability. Edit distance first, then embeddings with clustering over them, served behind an API and scored against a ground-truth set built for the purpose.

most of it
PythonJupyter
part of it
FastAPILangChainpandasscikit-learn
in passing
NumPy