DMN/Software

Web applications from schema to server.

Leon, full stack developer. Self-built web applications with React, Node.js and TypeScript.

Open to a permanent position, remote or hybrid in North Rhine-Westphalia.

View projects Contact

Projects

Five are live, four of them without signing up.

Time tracking

Working time, leave and flextime under the German Working Hours Act and Federal Leave Act, plus project time and invoices under § 14 of the VAT Act. Every figure can be expanded to show what it is made of: which bookings, which target, from which contract.

  • NestJS
  • React
  • PostgreSQL with row level security
  • e-invoicing

Source chat modeled on NotebookLM

Upload your own sources, ask about them in a chat and trace every statement in the answer back to the passage it came from. Citation numbers without a matching passage are dropped, every remaining one leads to its passage.

  • Next.js
  • NestJS
  • Postgres with pgvector
  • hybrid search

Status monitor

Monitors websites and servers, shows availability publicly and sends a mail when a service goes down and when it is back. A single hiccup raises no alarm, an outage only starts after several failed checks in a row.

  • Go
  • net/http
  • SQLite
  • Docker
Website
99.99 %
Job finder
99.99 %
Job finder API
99.99 %
Source chat
100.00 %

Availability over the last 30 days, as of

Remote job finder and application tracker

Finds remote jobs worldwide that can be taken from Germany and tracks your own applications. Many “remote” listings only apply to one country: it reads the requirement from every listing and shows the sentence that rules an excluded job out.

  • Next.js
  • Supabase
  • pgvector
  • pg-boss
  • Resend
  1. Scored3,389 jobs
  2. Above the score threshold370 jobs
  3. Eligible from Germany175 jobs

As of

Minigames

Twelve browser games with a leaderboard. The server replays every run from its inputs and computes the score itself, so the browser cannot dictate one.

  • Vite
  • React
  • TypeScript
  • Fastify
  • node:sqlite
  • Docker
  1. Browser sends only the inputs
  2. Server replays the run from the seed
  3. Server computes the score itself
  4. Leaderboard takes the result, with a rate limit per hashed IP

FRITZ!Box history

Records when each device was on the home network, for months instead of the few hundred lines the FRITZ!Box keeps itself. A collector written in Go reads the box over TR-064 through a WireGuard tunnel, and Postgres turns that into sessions per device. Where data is missing, the history shows a gap instead of “offline”.

  • Go
  • TR-064
  • PostgreSQL
  • pgTAP
  • React
View details

Private, reachable through a VPN only

How it is built

What runs through the projects above.

  1. The whole stack built by hand

    Database schema, API, interface and deployment are built together, not as separate parts.

    Real code from the minigames

    api/src/db.ts

    CREATE TABLE scores (  id          INTEGER PRIMARY KEY AUTOINCREMENT,  game        TEXT    NOT NULL,  name        TEXT    NOT NULL,  score       INTEGER NOT NULL,  duration_ms INTEGER NOT NULL,  created_at  INTEGER NOT NULL,  ip_hash     TEXT    NOT NULL);

    api/src/routes.ts

    app.post<…>(  '/score', …  async (req, reply) => {    const { token, log } = req.body    …    const game = session.game as GameId    const result = replay(SIMS[game],      session.seed, log)    const score = result.score

    web/src/shell/Leaderboard.tsx

    <div className="board">  <h3>Bestenliste</h3>  …    <ol>      {top.map((row) => (        <li key={`${row.rank}-${row.name}`} …>          <em>{row.name}</em>          <b>{row.score}</b>        </li>

    deploy/README.md

    cd $ZIELgit pullcd deploydocker compose up -d --builddocker compose ps…curl -s \  https://minigames.dmn-software.com/api/v1/health
    View code from the source chat
  2. Self-hosted

    The applications run in Docker containers behind Caddy on a rented server, set up and maintained by hand.

    Browser FiveM Client iframe HTTPS HTTPS only 80 and 443 80 redirects to 443 Caddy single entry · TLS Reverse proxy · HTTPS with Let's Encrypt internal HTTP dmn-software.com internal network Caddy static files Website API HTTPS API only reachable through the website minigames.dmn-software.com internal network Web · React API · Fastify SQL SQLite · Volume notebook.dmn-software.com internal network Web · Next.js Supabase Gateway SQL PostgreSQL pgvector API · NestJS HTTPS API bewerbungen.dmn-software.com internal network Web · Next.js Supabase Gateway Kong Auth · REST Storage Worker · pg-boss SQL PostgreSQL pgvector HTTPS API status.dmn-software.com internal network Status monitor · Go SQL SQLite · Volume zeit.dmn-software.com live and demo separate Web · React PDF worker API · NestJS SQL PostgreSQL row level security mail from live only FRITZ!Box history VPN only Web · React PostgREST GoTrue Collector · Go SQL PostgreSQL logic in SQL TR-064 · WireGuard External Resend · Mail Cloudflare Email Routing Mailbox AI providers Gemini, Claude Job boards and ATS FRITZ!Box over WireGuard Browser FiveM Client iframe HTTPS HTTPS only 80 and 443 80 redirects to 443 Caddy single entry · TLS Reverse proxy · HTTPS with Let's Encrypt internal HTTP dmn-software.com internal network Caddy · static files Website API HTTPS API only reachable through the website minigames.dmn-software.com internal network Web · React API · Fastify SQL SQLite Volume notebook.dmn-software.com internal network Web · Next.js PostgreSQL pgvector API · NestJS Supabase Gateway HTTPS API bewerbungen.dmn-software.com internal network Web · Next.js Supabase Gateway, Kong PostgreSQL pgvector Auth · REST Storage SQL Worker · pg-boss HTTPS API status.dmn-software.com internal network Status monitor · Go SQL SQLite Volume zeit.dmn-software.com live and demo separate Web · React PDF worker API · NestJS SQL PostgreSQL RLS mail from live only FRITZ!Box history VPN only Web · React PostgREST GoTrue Collector · Go SQL PostgreSQL SQL logic TR-064 · WireGuard External Cloudflare Email Routing Resend · Mail Mailbox AI providers Gemini, Claude Job boards and ATS FRITZ!Box over WireGuard
    • Contact form: The browser sends the form over HTTPS. Caddy terminates TLS and forwards to the website API. The website API checks input and limits. Resend sends the mail. Cloudflare Email Routing forwards it to the mailbox.
    • Minigame score: The client sends only inputs. The server replays the run from its seed. The score is stored in SQLite.
    • Question to the source chat: The question goes to the NestJS API. Hybrid search in Postgres with pgvector. Gemini writes the answer with citations.
    • Daily mail: The worker schedules the summary. Matches come from Postgres. Resend sends the mail.
    • Issuing an invoice: The browser sends the request to issue over HTTPS. Caddy forwards it to the time tracking API. Postgres hands out the next number, locked until commit. A worker thread renders the PDF.
    • FRITZ!Box poll: The collector polls the box on a schedule. Host list and log arrive over TR-064 through the WireGuard tunnel. New events land in Postgres, duplicate lines are dropped.
    Caddy is the only entry point from outside. Each application runs as its own Docker stack in its own internal network, and only Caddy is connected to all of them. Time tracking runs twice, separately, as live and as demo. The FRITZ!Box history cannot be reached from outside, and its collector reads the box over a WireGuard tunnel. External lists the services outside the server, and the dots show whether an application is reachable right now.
  3. The server computes what counts

    In the minigames the browser only sends inputs. The server computes the score itself, so the leaderboard cannot be fed with invented values.

  4. Traceable instead of a black box

    In the source chat every statement in an answer leads back to the passage in the source, instead of having to be taken on trust.

For FiveM servers

FiveM resources

Systems and tools for GTA V roleplay servers, such as banking, invoices and character selection. Most of them run on the versioned library dmn_base with database migrations and adapters for ESX, QBCore and Qbox.

Discord bot

A standalone bot for the Discord server that goes with the resources. Templates from a file and drafts from a language model go through the same schema check before it creates roles and channels.

View details

Not publicly accessible

dmn_banking: account overview with balance, income, expenses and history chart
dmn_carsteal: mission center with rank class 2, progress to the next class, completed missions and total earnings
dmn_base: keypad minigame with number pad

Interfaces rendered in the browser with sample data

Technology

Frontend
  • React
  • Next.js
  • SvelteKit
  • Svelte
  • Vue.js
  • Nuxt
  • TypeScript
  • JavaScript
  • HTML5
  • CSS3
  • Tailwind CSS
  • Bootstrap
Backend
  • Node.js
  • NestJS
  • PHP
  • Laravel
  • Java
  • Spring Boot
  • Go
  • Lua
  • REST APIs
  • Supabase Edge Functions
Databases
  • PostgreSQL
  • MySQL
  • MariaDB
  • MongoDB
  • Supabase
  • pgvector
  • SQL
  • Row Level Security
Mobile
  • Capacitor
  • Apps for iOS and Android
  • App Store
  • Google Play Store
DevOps and infrastructure
  • Docker
  • Git
  • GitLab CI/CD
  • AWS (EC2, S3, RDS)
  • Linux
  • Proxmox
  • Caddy
  • Nginx
  • Deployment
AI and search
  • RAG
  • Embeddings
  • Vector search
  • LLM Integration
  • Claude Code
Quality and methods
  • Unit Tests
  • automated tests
  • Code Reviews
  • Clean Code
  • technical documentation
  • Scrum
  • Jira
  • Confluence

Contact

Job offers, or questions about a project or the code: by mail or through the form.