Skip to content
05 / INŽENÝRSKÁ CASE STUDYFun Park Stonky · back office, web, předplacené kartyV PROVOZU OD 1. 10. 2026

FunOS.

Co se kontroluje před každým nasazením a po něm
  1. 01 Testy
  2. 02 Skutečná Postgres
  3. 03 Review agenti
  4. 04 Kontrola driftu
  5. 05 Záloha
  6. 06 Nasazení
  7. 07 Screenshot
  8. 08 Hlídač

Jeden člověk a Claude Code postavili systém, na kterém běží rodinný zábavní park: rezervace, dárkové poukazy, předplacené karty a obousměrné napojení na pokladnu. Tečou přes něj skutečné peníze zákazníků. Tohle je o disciplíně, díky které se kódu od AI dá věřit i s nimi.

KlientFun Park Stonky(funparkstonky.cz)
POSTAVIL DAVID RAJNOHA ·  KVĚTEN–ŘÍJEN 2026
Dolů
00Rejstřík projektu
Role
Jediný inženýrArchitektura, back office, integrace, nasazení, provoz
Klient
Fun Park StonkyRodinný zábavní park, čtyři provozovny
Období
Květen–říjen 2026Stav · v provozu od otevření
Stack
React · Supabase · Claude CodePostgres · edge funkce · Vercel
0
Testů běží v CI
0
Peněžních testů na skutečné Postgres
0
Migrací databáze
0
Commitů napsaných s Claude
01
Problém
Místo
Uherské Hradiště
Provozovny
Laser Game · dětský svět · herna · party room
Termín
Den otevření, 1. října 2026

Rodinný zábavní park se čtyřmi provozovnami pod jednou střechou. Rezervace, dárkové poukazy, předplacené karty, web i pokladna žily každý zvlášť a o sobě navzájem nevěděly. Pokladna věděla, co se prodalo. Nikdo nevěděl, jestli karta dobitá online bude u pultu opravdu fungovat. Těžká nebyla žádná jednotlivá obrazovka. Těžké bylo, aby se pět systémů shodlo na penězích, každou minutu, zatímco obsluha odbavuje frontu dětí.

Park otevírá k pevnému datu. Od té chvíle je každá chyba rodič u pultu s kartou, na které je špatné číslo, a rodinná firma, která to musí vysvětlovat.

Co se muselo shodnout
  • Pokladna · tržby, kredit, body
  • Předplacená karta v kapse zákazníka
  • Dobití a platby poukazů online
  • Rezervace z webu i od obsluhy
  • Back office, ze kterého majitelé řídí den
  • Zákaznický účet na webu
„Obrazovka, která vypadá správně, je snadná. Peníze, které sedí v pokladně, v back office i v telefonu zákazníka zároveň, jsou ten skutečný produkt.“
02
Teze

Kód píše AI. Jestli se nasadí, rozhoduje disciplína. Každé pravidlo tady vzniklo z toho, že jednou něco proklouzlo.

Většinu systému napsal Claude Code, a rychle. Rychlost ale nikdy nebyla riziko. Riziko je kód, který se zkompiluje, projde vlastními testy a v penězích se stejně plete. Práce se proto přesunula: méně psaní, víc rozhodování o tom, co musí platit, a stavění strojů, které to pokaždé zkontrolují.

Co zůstává na mně
  • Co musí platit o penězích a co se nesmí stát nikdy
  • Číst incident, ne jen diff
  • Z každé uniklé chyby udělat test nebo guard
  • Nasazení v pevném pořadí, vždycky nejdřív záloha
  • Říct „ještě ne“, když backend není hotový
Co dělá stroj
  • Píše kód, migrace i testy
  • Pustí celé CI lokálně, než pushnu
  • Projde každou změnu čtyřmi až šesti pohledy
  • Schválně rozbije vlastní testy, aby dokázal, že kousnou
  • Porovná produkci s repem, oběma směry
03
Co vzniklo

Čtyři plochy, jedna databáze, jeden zdroj pravdy.

Obě aplikace i všechny integrace čtou a zapisují jednu databázi Postgres. Pravidla přístupu žijí v databázi, ne v UI: schované tlačítko není oprávnění.

  • Web37 rout

    Veřejný web

    Rezervace s živou obsazeností podle provozovny, dárkové poukazy s online platbou, poptávky oslav a zákaznický portál se zůstatkem karty, body a dobitím online. Předrenderovaný, takže se dá číst i bez JavaScriptu.

  • FunOS33 obrazovek

    Back office

    Rezervace, akce, poukazy, evidence karet, zákazníci, směny a výplaty zaměstnanců, tržby z pokladny, zprávy z webu, mapa zákaznických cest a stránka se zdravím systému.

  • KartaPokladna + FunOS + web

    Předplacená karta StonkyPass

    Kredit žije v nativním zákaznickém kreditu pokladny, takže platba je jedno pípnutí u pultu. Body a úrovně zrcadlí FunOS. Ztracená karta se jedním krokem zablokuje v pokladně i ve FunOS a pak vymění za novou i se zůstatkem.

  • ProvozBěží beze mě

    Provoz

    Hlídač, který při poruše pošle e-mail, kanárek, který každou hodinu přečte kontrolní kartu v pokladně, denní šifrované zálohy s vyzkoušenou obnovou a kontrola každé tři hodiny, že na produkci běží to, co je v main.

04
Architektura

Všechno se potká v Postgres. Každá šipka má kontrolu.

Dvě React aplikace, jeden projekt Supabase. Pravidla, která sahají na peníze, běží uvnitř databáze, kde zabezpečení na úrovni řádků rozhoduje, kdo smí co číst a zapisovat. Edge funkce mluví s okolním světem, plánované úlohy drží pokladnu a FunOS ve shodě.

Lidé
Zákazník
Web · telefon · karta
Obsluha u pultu
FunOS · pokladna
Majitelé
FunOS · přehledy
Jádro
Postgres
Zabezpečení řádků · kreditní ledger jen pro zápis
Edge funkce
18 · platby, pokladna, e-maily
Plánované úlohy
Sync s pokladnou po pár minutách
Okolí
Pokladna Dotykačka
Tržby, kredit, body — oběma směry
Comgate
Platby kartou
Resend · Sentry · PostHog
E-maily · chyby · analytika se souhlasem
Kolem toho
  • CI se třemi joby: build, peněžní sada na skutečné databázi, web + testy v prohlížeči
  • Denní šifrovaná záloha, obnova vyzkoušená
  • Kontrola nasazených verzí každé 3 hodiny
  • Hlídač provozu + kanárek pokladny, e-mail při poruše
05
Jedna karta, jedno odpoledne

Dobití u pokladny se musí objevit všude. Aniž by ho kdokoli psal dvakrát.

Takhle projde systémem jedna předplacená karta. Zapisují do ní čtyři různé programy. Když se kterýkoli z nich rozejde s ostatními, zákazník vidí špatné číslo.

FUN PARK STONKY
Ilustrační data
KartaDEMO-0042
  1. 14:02PokladnaDobití u pultu+500 Kč
  2. 14:04SyncZrcadleno do FunOS500 Kč
  3. 15:40PokladnaLaser Game, placeno kartou−180 Kč
  4. 15:42SyncÚtrata zrcadlena, přičteny body+18 b
  5. 18:10WebZákazník kouká do portálu320 Kč
  6. 18:10FunOSObsluha vidí stejný zůstatek320 Kč
Zůstatek všude320 Kč · 18 b

Stejné číslo v pokladně, v back office i v telefonu zákazníka.

Díky čemu to platí
  1. 01

    Pravdu o kreditu drží pokladna. FunOS ji zrcadlí a stejný pohyb nikdy nepošle zpátky dvakrát.

  2. 02

    Kredit je ledger pohybů, nikdy přepsaný zůstatek. Oprava je nový řádek, ne změněný.

  3. 03

    Body vznikají jen z kreditu utraceného za vstupné a hry, podle pravidla parku.

  4. 04

    Každou hodinu kanárek přečte kontrolní kartu v pokladně a porovná ji s FunOS.

06
Klíčová rozhodnutí

Rozhodnutí, která jsou schválně nudná.

Kreditní ledger je jen pro zápis
Zůstatek se počítá z pohybů. Nikdo, ani já, zůstatek nepřepisuje. Když je něco špatně, oprava je další řádek a historie zůstane čitelná.
Platební webhooky jsou idempotentní
Platební brána zavolá dvakrát, klidně desetkrát. Stejná platba musí připsat přesně jednou. Po opakovaném selhání systém přestane zkoušet sám a zeptá se člověka.
Nebrat peníze, které nejde doručit
Než zákazník zaplatí dobití online, systém ověří, že kartu v pokladně opravdu najde. Když ne, na platební bránu ho vůbec nepošle.
UI nikdy nepředběhne backend
Když databáze něco ještě nepřijme, obrazovka řekne „připravujeme“, místo aby nechala zákazníka dojít flow, které na posledním kroku spadne. Na produkci jde vždycky nejdřív backend.
Oprávnění mají dvě strany
Schovaná záložka není kontrola přístupu. Každá změna rolí se kontroluje v UI i v politikách databáze a test obojí porovnává.
Souhlas před cookies
Návštěvy se měří bez cookies, dokud se návštěvník nerozhodne. Odmítnout jde stejně snadno jako povolit, jak čeká ÚOOÚ, a odvolání smaže, co se uložilo.
07
Jak stavím s AI

„Ověřeno“ znamená spuštěno, ne že to někdo přečetl.

Psaní dělá Claude Code. Kolem něj je smyčka, díky které můžou systémem téct skutečné peníze: každý krok buď něco spustí, nebo vyrobí důkaz, a změna je hotová, až když důkaz existuje.

  1. 01Zadání

    Požadavek přijde obyčejnou češtinou od lidí, kteří park provozují. Udělám z něj, co musí platit a co se nesmí stát nikdy.

  2. 02Stavba

    Claude Code pracuje na větvi ve vlastním worktree. Malé fáze, každá ověřitelná sama o sobě.

  3. 03CI lokálně

    Jeden skript pustí přesně to, co CI. Když změna sahá na peníze, odmítne skončit zeleně bez sady na skutečné Postgres.

  4. 04Review

    Čtyři až šest review agentů čte diff různými pohledy: bezpečnost, správnost, okrajové případy a jeden, který vidí jen samotný diff.

  5. 05Rozbít

    Mutační kontrola: rozbiju to, co nový test hlídá. Když test pořád projde, byla to dekorace a píše se znovu.

  6. 06Nasazení

    Kontrola driftu, záloha databáze, migrace, funkce, pak build webu na skryté adrese. Na doménu jde až po kontrole.

  7. 07Podívat se

    Screenshot skutečné produkční obrazovky a hlídač po nasazení. Zelený build nikdy nebyl cíl.

Guardy — každý z jednoho incidentu
Privilegované funkce vs. politiky tabulek
Funkce se zvýšenými právy nesmí pustit víc rolí, než dovolí sama tabulka.
Shoda napříč vrstvami
Enumy v databázi vs. mapy v UI, role v UI vs. role v databázi, volané funkce vs. migrace.
Odkazy, které existují
Každý odkaz v e-mailu nebo SMS musí vést na skutečnou routu webu.
Anonymní přístup
Co smí spustit návštěvník bez přihlášení, je výslovný seznam. Peněžní funkce na něm nejsou.
Strop přeskočených testů
Počet tiše přeskočených testů nesmí růst.
Drift produkce
Produkce vs. repo oběma směry, včetně toho, jaká verze které funkce je nasazená.
kontrola driftu · 19. 10. 2026
$ node scripts/prod-drift-check.mjsEdge funkce (18 nasazených, 18 v repu)Brána nasazených funkcí sedí s konfiguracíNasazené funkce odpovídají mainu (žádná není starší)Migrace (222 celkem)Konfigurace Auth (SMTP, šablony e-mailů, limity)# exit 1 = drift → nenasazovat
Pouští se před každým nasazením a sama každé tři hodiny. Vznikla, protože jednou nasazení smazalo živou obrazovku, kterou produkce měla a repo ne.
Chyceno dřív, než to viděl zákazník
  • Role ořezané jen v UI

    Změna snížila počet rolí z osmi na pět v rozhraní. Databáze ale znala staré: zrušený externí účet by propadl do celého back office. Teď test porovnává role v UI s rolemi v databázi.

  • Blokátor reklam, který by obnovil formulář

    Review změny s analytikou zjistilo, že blokátor reklam, který zablokuje soubor analytiky, by spustil obnovu po nasazení a smazal rozepsanou rezervaci. Opraveno před merge, i s testem.

  • Tabulka, kterou úloha na pozadí nepřečte

    Peněžní sada na čisté databázi ukázala, že nová tabulka nemá práva pro servisní účet. Na produkci by úloha na dohánění nikdy nic nedohnala.

08
Co se rozbilo

Tři incidenty, tři nové stroje.

Každý z nich prošel buildem, testy i lidským okem. Ani jeden se nedal najít čtením. Na každý teď něco běží.

  1. 15. 8. 202601

    Nasazení smazalo živou obrazovku

    Co se stalo
    Registrace karty se nasadila ručně a nikdy nezmergovala. Další nasazení z main ji z produkce odstranilo. Build zelený, testy zelené, funkce pryč.
    Co existuje teď
    Kontrola driftu, která porovná produkci s repem oběma směry. Návratový kód 1 znamená nenasazovat.
  2. 19. 8. 202602

    CI dva dny červené a nikdo si nevšiml

    Co se stalo
    Selhání se schovalo za zeleným krokem s testy. Migrace nešly aplikovat na prázdnou databázi a databáze postavená jen z migrací byla nepoužitelná: práva udělená kdysi ručně se do repa nikdy nedostala.
    Co existuje teď
    Job v CI, který při každé peněžní změně postaví databázi od nuly a pustí proti ní peněžní sadu.
  3. 9. 10. 202603

    Zaplacené dobití, které nedorazilo

    Co se stalo
    Oprava hledání karty v pokladně byla v repu, ale platební funkce na produkci byla starší. Zákazník zaplatil online a kredit nedorazil. Připsal se ručně, až když byly oba systémy ověřené.
    Co existuje teď
    Žádná platba, dokud se karta nenajde, žádné nekonečné automatické pokusy a každé tři hodiny kontrola, že produkce běží to, co je v main.
09
Časová osa

Od prvního commitu do dne otevření a dál.

  1. První commit

    Přestavba raného prototypu na produkční stack: vlastní databáze, vlastní hosting, testy od prvního dne.

  2. Zpevněný web, napojené platby

    Validace vstupů, platební brána a první CI.

  3. Pokladna mluví s FunOS

    Tržby z pokladny chodí do back office samy.

  4. Řetěz karty ověřený naživo

    Spárování, dobití u pokladny, sync, back office, web — od začátku do konce na skutečné kartě.

  5. Guardy a peněžní sada

    Testy napříč vrstvami a job v CI na skutečné databázi.

  6. Audit před otevřením

    Peněžní cesty, práva v databázi a limity přihlášení prověřené a nasazené.

  7. Den otevření

    Rezervace v provozu, denní šifrované zálohy běží.

  8. Oči na produkci

    Sledování chyb bez osobních údajů, hlídač provozu a kanárek pokladny.

  9. Ztracené karty a analytika

    Blokace a výměna karty v pokladně i ve FunOS najednou; analytika webu se souhlasem.

10
Čísla

Jen to, co je změřené.

Spočítáno na hlavní větvi a v jejích CI lozích 19. října 2026. Jen technická čísla: tržby, počty zákazníků a objem kreditu patří parku, ne téhle stránce.

1 544
Unit testů back office
+ 285, které potřebují živé přístupy
626
Unit testů webu
Vitest
131
Testů v prohlížeči
Playwright, vč. přístupnosti
263
Peněžních testů na skutečné Postgres
databáze postavená od nuly
190
Testů edge funkcí
Deno
6
Automatických guardů
každý ze skutečného incidentu
222
Migrací databáze
24 572 řádků SQL
62 711
Řádků TypeScriptu
bez testů a generovaných typů
194
Mergnutých pull requestů
826 commitů
11
Poctivé limity

Co tohle není.

  1. 01

    Není to kód jednoho člověka. Vývojář na straně parku upravuje ve stejném repu obsah webu, provozovny a ceny — asi 18 % commitů. Inženýrství, peněžní cesty a provoz jsou moje.

  2. 02

    Hosting i databáze dnes běží na free tarifech. Zálohy mám vlastní, denní a šifrované, s vyzkoušenou obnovou. Placené tarify jsou na cestě.

  3. 03

    Ani jedna aplikace zatím nejede TypeScript ve strict režimu. Je to zapsaný dluh, ne schovaný; zapnutí je samostatná velká změna.

  4. 04

    Jeden incident k zákazníkovi doputoval dřív, než na něj guard existoval. Peníze se srovnaly, guard přišel potom.

  5. 05

    API pokladny se chová i způsobem, který v dokumentaci není. Kanárek kontroluje odpovědi každou hodinu, ale změna u dodavatele nás pořád může překvapit první.

  6. 06

    Analytika webu běží od 14. října. Data o konverzích zatím nejsou, takže tahle stránka žádná netvrdí.

Kontroly jsou produkt.

Rezervační formulář dnes z modelu dostane kdokoli. Čas zabral seznam věcí, které se penězům zákazníků už nikdy nesmí stát — a stroje, které je kontrolují při každé změně.