{"id":674,"date":"2026-09-12T11:41:53","date_gmt":"2026-09-12T09:41:53","guid":{"rendered":"https:\/\/www.pmannel.de\/wordpress\/?p=674"},"modified":"2026-09-12T11:41:53","modified_gmt":"2026-09-12T09:41:53","slug":"mtb-service-app-eine-pwa-komplett-mit-claude-code-gebaut","status":"publish","type":"post","link":"https:\/\/www.pmannel.de\/wordpress\/mtb-service-app-eine-pwa-komplett-mit-claude-code-gebaut\/","title":{"rendered":"MTB Service App: eine PWA komplett mit Claude Code gebaut"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Nach ganz langer Zeit mal wieder ein Artikel zu einem kleinen Projekt von mir&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ich fahre viel Mountainbike, und wie bei jedem Bike stellt sich irgendwann die Frage: Wann war eigentlich der letzte Service dran? Kette, Bremsen, Gabel \u2013 jedes Teil hat sein eigenes Intervall, und ohne System und beson ders bei vielen R\u00e4dern vergisst man das zuverl\u00e4ssig. Also habe ich mir kurzerhand eine eigene App gebaut: die MTB Service App, live unter <a href=\"https:\/\/service-log.online\">service-log.online<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Man kann f\u00fcr beliebig viele Bikes protokollieren, wann welcher Service f\u00e4llig ist \u2013 nach Kalenderzeit oder nach gefahrenen Stunden, je nach Verschlei\u00dfteil. Neben den \u00fcblichen Verd\u00e4chtigen wie Federgabel, Kette oder Bremsen lassen sich auch eigene Service-Typen anlegen. Die App l\u00e4uft als PWA, funktioniert offline und ist zweisprachig auf Deutsch und Englisch.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So sieht das im Alltag aus: die Bike-\u00dcbersicht, die Service-Tabelle eines einzelnen Bikes, \u00fcberf\u00e4llige und erledigte Services auf einen Blick sowie der Dialog zum Eintragen eines neuen Service.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot.jpg\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"420\" data-id=\"675\" src=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot-1024x420.jpg\" alt=\"Startseite von service-log.online\" class=\"wp-image-675\" srcset=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot-1024x420.jpg 1024w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot-300x123.jpg 300w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot-768x315.jpg 768w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot-1536x630.jpg 1536w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/service-log-screenshot.jpg 1568w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht.png\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"376\" data-id=\"678\" src=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht-1024x376.png\" alt=\"\u00dcbersicht der Bikes in der MTB Service App\" class=\"wp-image-678\" srcset=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht-1024x376.png 1024w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht-300x110.png 300w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht-768x282.png 768w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht-1536x564.png 1536w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bikes-uebersicht.png 1568w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail.png\" data-rel=\"lightbox-image-2\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"376\" data-id=\"679\" src=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail-1024x376.png\" alt=\"Bike-Detailansicht mit Service-Tabelle in der MTB Service App\" class=\"wp-image-679\" srcset=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail-1024x376.png 1024w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail-300x110.png 300w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail-768x282.png 768w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail-1536x564.png 1536w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-bike-detail.png 1568w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht.png\" data-rel=\"lightbox-image-3\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"376\" data-id=\"680\" src=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht-1024x376.png\" alt=\"Status-\u00dcbersicht mit \u00fcberf\u00e4lligem und OK-Service in der MTB Service App\" class=\"wp-image-680\" srcset=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht-1024x376.png 1024w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht-300x110.png 300w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht-768x282.png 768w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht-1536x564.png 1536w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-status-uebersicht.png 1568w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen.png\" data-rel=\"lightbox-image-4\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"376\" data-id=\"681\" src=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen-1024x376.png\" alt=\"Formular zum Eintragen eines Service in der MTB Service App\" class=\"wp-image-681\" srcset=\"https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen-1024x376.png 1024w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen-300x110.png 300w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen-768x282.png 768w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen-1536x564.png 1536w, https:\/\/www.pmannel.de\/wordpress\/wp-content\/uploads\/app-service-eintragen.png 1568w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Das eigentlich Interessante an dem Projekt ist aber weniger die App selbst, sondern wie sie entstanden ist: nahezu vollst\u00e4ndig mit Claude Code, Anthropics KI-gest\u00fctzter Kommandozeile f\u00fcr Softwareentwicklung. Statt Copilot-artiger Zeilenvervollst\u00e4ndigung l\u00e4uft hier ein Agent, der ganze Features eigenst\u00e4ndig umsetzt \u2013 von der Datenbank-Migration \u00fcber den API-Endpunkt bis zum Alpine.js-Template im Frontend, inklusive Tests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit das \u00fcber viele Sessions hinweg konsistent bleibt, pflege ich eine CLAUDE.md im Repo: Architekturentscheidungen, Konventionen (etwa dass jeder Endpoint Ownership manuell per user_id pr\u00fcft, weil es bewusst keine ORM gibt) und wie neue Sprachstrings durch Lang::t() beziehungsweise i18n.js laufen m\u00fcssen. Claude liest diese Datei bei jeder Aufgabe und h\u00e4lt sich \u00fcberraschend zuverl\u00e4ssig daran \u2013 das hat mich am meisten \u00fcberzeugt, gerade bei einem Projekt ohne Framework, wo sonst leicht alles ausfranst.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Technisch ist die App bewusst simpel gehalten: PHP 8.1 prozedural mit ein paar kleinen Klassen, kein Framework, kein Router, keine ORM \u2013 \u00c4nderungen wirken sofort nach dem Neuladen, ohne Build-Schritt. Vanilla JS mit Alpine.js f\u00fcr die Oberfl\u00e4che, MySQL als Datenbank, PHPUnit f\u00fcr die Tests der Business-Logik. Genau die Art von Codebase, in der ein KI-Agent seine St\u00e4rken ausspielt: \u00fcberschaubar genug, um sie komplett im Kontext zu halten, aber gro\u00df genug, dass man beim manuellen Durcharbeiten Zeit verliert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wer selbst Mountainbikes wartet und den \u00dcberblick \u00fcber Service-Intervalle behalten will, kann die App unter <a href=\"https:\/\/service-log.online\">service-log.online<\/a> kostenlos ausprobieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Und was das Allerbeste ist, weder diesen Text, die Bilder, noch den Artikel habe ich selbst geschrieben oder in WordPress angelegt, auch das hat Claude \u00fcbernommen<\/strong>&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wie ich die MTB Service App fast vollst\u00e4ndig mit Claude Code gebaut habe \u2013 und was ich dabei \u00fcber CLAUDE.md, Konventionen und den Umgang mit einem KI-Agenten in einer schlanken PHP-Codebase gelernt habe.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ai_generated_summary":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"wpai_meta_description":"","footnotes":"","jetpack_post_was_ever_published":false},"categories":[87,1],"tags":[92,89,88,90,91,93],"class_list":["post-674","post","type-post","status-publish","format-standard","hentry","category-ai","category-allgemein","tag-alpine-js","tag-claude","tag-claude-code","tag-ki","tag-php","tag-pwa"],"jetpack_shortlink":"https:\/\/wp.me\/p1yA6S-aS","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/posts\/674","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/comments?post=674"}],"version-history":[{"count":11,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/posts\/674\/revisions"}],"predecessor-version":[{"id":699,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/posts\/674\/revisions\/699"}],"wp:attachment":[{"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/media?parent=674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/categories?post=674"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pmannel.de\/wordpress\/wp-json\/wp\/v2\/tags?post=674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}