Objednávka projde od košíku přes účetnictví až po spárovanou platbu, aniž by se jí kdokoliv dotkl
Můj vlastní web. Bezpečnost práce a požární ochrana jako živnost, ale postavená jako systém: e-shop, zákonná školení s certifikátem, evidenční moduly pro firmy a k tomu tři tisíce šest set stránek obsahu, ze kterého chodí poptávky.
20
kroků objednávky bez ručního zásahu
Od udělení přístupu přes provize a licence až po fakturu a e-mail
src/lib/order-completion.ts
3
systémy, které si povídají samy
Platební brána, účetní systém a bankovní výpisy, bez přepisování mezi nimi
Integrace ThePay, iDoklad a Fio banka
3 625
adres na jednom webu
Články, videa, produkty, karty rizik, předpisy a stránky služeb
Produkční sitemap.xml, 31. 7. 2026
655
lekcí v osmi kurzech
S kvízy, checklisty a certifikátem na konci
Rozcestník kurzů na produkci, 31. 7. 2026
119 + 825
blogových článků a videí
Obsah, ze kterého chodí poptávky
Produkční sitemap.xml, 31. 7. 2026
303
tabulek v jedné databázi
E-shop, e-learning, blog, inzerce, rizika, dokumenty, úrazy
prisma/schema.prisma, 159 migrací
- E-shop s okamžitým dodáním
- Peníze projdou od košíku po zaúčtovanou fakturu samy
- Zákonná školení s certifikátem, ne video ke stažení
- Firemní účty se školicí maticí
- Jeden účet pro všechny moje aplikace
- Administrace, která nahradila tabulky
- Obsah jako zdroj poptávek
- Párování plateb, které počítá s realitou
- Objednávka se neuzavře, dokud nedoběhne všech dvacet kroků
- Platební brána, které se nevěří na slovo
- Certifikát, který si kdokoliv ověří bez přihlášení
- Fakturační údaje se vyplňují jednou pro všechno
- Jedna aplikace obsluhuje tři domény
- Statistiky se počítají z účetních dat, ne z měřicího skriptu
- Provoz se hlídá sám
- Databáze rizik zdarma jako vstupní brána
- Sedm samostatných produktů s předplatným
- Inzertní portál pro obor
- Zákazník si postaví vlastní kurz
Zadání
Tohle není zakázka. Je to můj vlastní web a zároveň moje pracovní laboratoř. Patnáct let chodím po provozech jako bezpečnostní technik a tu agendu znám zevnitř: dokumentace, školení, hodnocení rizik, evidence úrazů. Věci, které firmy dělají v Excelu a v šanonech, protože jim nikdo nepostavil nástroj.
Původní weby běžely na WordPressu, e-shop na jeho nákupní nadstavbě. V dnešní databázi po tom zůstaly stopy, sloupce s původními identifikátory. Roky to stačilo, pak přestalo. Web byl pomalý, administrace nepříjemná na ovládání a s každým dalším doplňkem přibyla věc, kterou jsem musel hlídat a aktualizovat, aniž bych viděl dovnitř.
Pak mi jedním z těch doplňků e-shop napadli a udělali nepořádek v objednávkách. Data jsem nakonec narovnal, ale stálo to spoustu hodin, které nikdo nezaplatil, a po celou dobu jsem nemohl zákazníkům s jistotou říct, co se s jejich objednávkou stalo. Tohle je zkušenost, kvůli které dnes nestavím na cizích zásuvných modulech. Každý z nich je cesta dovnitř, kterou neovládám a za kterou nemůžu ručit.
K tomu provoz. Každá objednávka znamenala ruční vystavení faktury, ruční kontrolu výpisu z banky a ruční odeslání souborů. Školení se prodávalo jako soubor ke stažení, takže zákazník neměl doklad o proškolení, který by obstál před kontrolou.
Rozhodl jsem se to postavit znovu a od základu. Ne jako web s doplňky, ale jako jednu aplikaci nad jednou databází, kde vím o každém řádku kódu, proč tam je.
Návrh
První rozhodnutí bylo nedělit to na tři nakoupené služby. Obvyklá cesta je web na jednom řešení, e-shop na druhém a e-learning jako pronajatá služba placená za uživatele. Tři účty, tři měsíční platby a zákazník existující třikrát, pokaždé trochu jinak. Chtěl jsem, aby objednávka, kurz a faktura mluvily o téže osobě.
Druhé rozhodnutí bylo, že peníze nesmí procházet rukama. Ne kvůli pohodlí, ale kvůli chybovosti. Ruční přepis částky a variabilního symbolu je místo, kde vzniká rozdíl mezi tím, co je v e-shopu, a tím, co je v účetnictví. Číslo objednávky proto vzniká jako čistě numerické a slouží rovnou jako variabilní symbol.
Třetí rozhodnutí se týkalo obsahu. Bezpečnost práce je obor, kde lidé hledají odpověď na konkrétní otázku, ne dodavatele. Encyklopedie rizik je proto zdarma, bez registrace a v plném rozsahu. Placený registr rizik z ní pak staví to samé pro konkrétní firmu, takže obsah zdarma a produkt sdílejí jedna data a neudržují se dvakrát.
Čtvrté rozhodnutí bylo o důvěře v cizí systémy. Platební bráně se nevěří na slovo, účetnímu systému se nedovolí zablokovat zákazníka a bankovní výpis se považuje za nespolehlivý zdroj, který může dorazit pozdě, dvakrát, nebo v částech.
Řešení
Web běží na Next.js, obsah i obchodní data jsou v PostgreSQL a stránky se skládají na serveru. Jedna aplikace přitom obsluhuje tři domény: podle adresy se přepne režim a pustí se jen odpovídající část.
Přihlášení nepatří téhle aplikaci. Postavil jsem k němu samostatný server, který funguje jako jediná identita pro všechno, co provozuji: web, e-learning, evidenci úrazů i odborné fórum. Bezpečák je vůči němu jen klient, který se přihlašuje přes OAuth2 a OpenID Connect s PKCE. Session cookie je sdílená napříč doménami a platnost přihlášení se ověřuje proti databázi každých patnáct vteřin, takže odhlášení nebo změna hesla platí všude okamžitě. Zákazník tak má jeden účet a jedny fakturační údaje, i když nakupuje ve třech různých aplikacích.
Peněžní okruh. Platba kartou přes bránu vystaví ostrou fakturu v účetním systému. Platba převodem vystaví nejdřív zálohovou fakturu a po připsání peněz ji na ostrou konvertuje. Bankovní výpis se stahuje každých patnáct minut a páruje podle variabilního symbolu s tolerancí jednoho haléře, protože zaokrouhlení daně je legitimní rozdíl, zatímco tolerance jedné koruny už je náplast. Dvě částečné platby se sečtou, nedoplatek se eviduje a zákazník o něm ví.
Dokončení objednávky je fronta dvaceti kroků, každý s vlastním identifikátorem a pěti pokusy. Opakovací úloha běží každých pět minut. Objednávka se uzavře jen tehdy, když prošla faktura i všechny kritické kroky, takže stav dokončeno vždycky něco znamená.
Školení nejsou videa ke stažení. Průchod hlídá pořadí lekcí, minimální čas nad lekcí, povinné checklisty a složené kvízy. Otázky se v okamžiku pokusu zmrazí i s otiskem, takže je zpětně vidět, na co student odpovídal. Certifikát nese otisk SHA-256 a QR kód, přes který si pravost ověří kdokoliv bez přihlášení.
Provoz běží v Dockeru za Caddy, ven nevede žádný port. Nasazení má tři úrovně podle rizika, od kompletního s povinnou zálohou po rychlé za třicet vteřin. Skript odmítne poslat na produkci necommitnutý strom. Záloha databáze se ověřuje čtením zpátky a existuje skript na cvičnou obnovu.
Výsledek
Web dnes obsluhuje tři tisíce šest set dvacet pět adres v padesáti sekcích: sto devatenáct článků, osm set dvacet pět videí, sedm set devadesát jedna karet rizik, sto devadesát osm produktů, sto dvacet sedm stránek k předpisům a devadesát stránek služeb. Osm kurzů má dohromady šest set padesát pět lekcí.
Ruční kroky mezi e-shopem, účetnictvím a bankou: žádné. Faktura vzniká sama, platba se páruje sama, zákazník dostane soubor nebo přístup do kurzu okamžitě. Pod tím běží třicet osm automatických úloh a administrace o devadesáti osmi obrazovkách.
Proti běžné konkurenci v oboru je rozdíl hlavně v tom, co se neplatí a co se nepřepisuje. Obvyklá sestava je prezentace na hotovém řešení, e-shop jako nadstavba a e-learning pronajatý za uživatele a měsíc. Tady je to jedna aplikace: nejsou tu poplatky za studenta, nejsou tu tři administrace a zákazník existuje jednou. Zákonná školení navíc většina webů v oboru vůbec neprodává, protože samotný soubor ke stažení neobstojí jako doklad o proškolení. A není tu žádný cizí doplněk, který by někdo musel hlídat a přes který by se dalo dostat dovnitř.
V čem je web opravdu silný: v propojení obsahu s prodejem. Encyklopedie rizik a videa přivádějí lidi na konkrétní otázku, článek je propojený s produktem, který ji řeší, a nákup končí přístupem, ne příslibem. To je věc, kterou nakoupená sestava nástrojů neumí, protože každý z nich vidí jen svůj kousek.
Co se právě dělá: optimalizace rychlosti úvodní stránky a vlastní měření návštěvnosti bez cizích skriptů. Obchodní statistiky se už dnes počítají serverově přímo z účetních tabulek, takže odpovídají tomu, co je na faktuře.
Co web umí a co z toho klient má
Jádro zadání
7 funkcíCo klient chtěl a bez čeho by web nefungoval
E-shop s okamžitým dodáním
Sto devadesát osm produktů v katalogu: směrnice, pověření, formuláře, desetiminutovky, požární dokumentace. Zákazník platí kartou a soubor má hned, bez čekání na člověka.
Technická poznámka
Odkaz ke stažení má platnost rok, počítá stažení a vede log s IP adresou. Velké soubory se nikdy nepřenášejí přes aplikaci: server vrátí přesměrování na podepsanou adresu úložiště s platností pět minut.
Peníze projdou od košíku po zaúčtovanou fakturu samy
Platba kartou vystaví ostrou fakturu. Platba převodem vystaví nejdřív zálohovou, a po připsání peněz se konvertuje na ostrou. Bankovní výpis se stahuje sám a páruje podle variabilního symbolu.
Technická poznámka
Číslo objednávky je záměrně čistě numerické (datum a pořadí), takže slouží přímo jako variabilní symbol. Tím odpadá překladová tabulka mezi e-shopem a bankou, což je místo, kde se párování obvykle rozbíjí.
Zákonná školení s certifikátem, ne video ke stažení
Osm kurzů a šest set padesát pět lekcí s kvízy, checklisty a interaktivními cvičeními. Student neprojde dál, dokud nesplní povinné části, a na konci dostane certifikát.
Technická poznámka
Dokončení hlídá pět nezávislých podmínek: pořadí lekcí, minimální čas nad lekcí, povinný checklist, složené kvízy a teprve pak certifikát. Bez toho by doklad o proškolení neobstál před kontrolou.
Firemní účty se školicí maticí
Firma si vede skupiny, podskupiny a oddělení, přiřazuje kurzy pozicím a vidí, komu školení propadá. Opakovaná školení se obnovují sama podle nastavené periody.
Technická poznámka
Povinné kurzy nevisí na jménech, ale na pracovních pozicích. Nový svářeč tak dostane správnou sadu školení tím, že se zařadí na pozici, ne tím, že si na něj někdo vzpomene.
Jeden účet pro všechny moje aplikace
Web, e-learning, evidence úrazů i odborné fórum sdílejí jedno přihlášení. Stojí na přihlašovacím serveru, který jsem k tomu postavil, takže identita zákazníků nepatří žádné cizí službě.
Technická poznámka
OAuth2 a OpenID Connect s PKCE proti vlastnímu serveru account.safetyfrog.cz. Platnost přihlášení se ověřuje proti databázi každých patnáct vteřin, takže odhlášení nebo změna hesla platí ve všech aplikacích okamžitě, ne až vyprší token.
Administrace, která nahradila tabulky
Devadesát osm obrazovek: produkty, objednávky, reklamace, kurzy, skupiny, blog, newsletter, prodejci, provize, audit log. Žádný plugin, žádná aktualizace zvenčí.
Technická poznámka
Devadesát osm obrazovek by se v cizím redakčním systému skládalo z pluginů od různých autorů. Tady je to jedna aplikace nad jedním schématem, takže objednávka, kurz a faktura mluví o téže osobě.
Obsah jako zdroj poptávek
Sto devatenáct článků, osm set dvacet pět videí a sto dvacet sedm stránek k předpisům. Přes tři tisíce šest set adres, na které lidé chodí z vyhledávačů, a odtud do e-shopu.
Technická poznámka
Strukturovaná data jsou ve sto jedenácti souborech: články, otázky a odpovědi, návody, drobečková navigace, videa. K tomu tři sitemapy, z toho jedna zvlášť pro video.
Vychytávky
8 funkcíDetaily, které nikdo nezadal a dělají rozdíl
Párování plateb, které počítá s realitou
Tolerance je jeden haléř, ne jedna koruna. Dvě částečné platby se sečtou do jedné objednávky. Nedoplatek se eviduje a zákazník o něm ví, přeplatek se ohlásí.
Technická poznámka
Platba, která dorazí dřív než objednávka, se uloží jako nespárovaná a dopáruje se zpětně. U nespárovaných částek systém navrhne podobná čísla objednávek, aby šlo řešit překlep ve variabilním symbolu.
Objednávka se neuzavře, dokud nedoběhne všech dvacet kroků
Přístup ke kurzu, provize, licence, faktura, e-mail. Každý krok má vlastní identifikátor a pět pokusů, opakovací úloha běží každých pět minut.
Technická poznámka
Přístup k obsahu se uděluje před fakturací, ne po ní. Výpadek účetního systému tak nikdy neblokuje zákazníka: objednávka zůstane ve stavu zaplaceno, faktura se dotáhne později a administrátor o tom ví.
Platební brána, které se nevěří na slovo
Podpis notifikace se ověřuje v konstantním čase, každá notifikace jde do logu a duplicitu blokuje unikátní index v databázi. Skutečný stav platby si systém vždy dotáhne zpátky od brány.
Technická poznámka
Nezávisle na notifikacích běží každých deset minut srovnávací úloha, která dohání ztracené zprávy. Notifikace, která dorazí dřív než zápis objednávky, dostane odpověď 202 a brána ji zopakuje.
Certifikát, který si kdokoliv ověří bez přihlášení
Na certifikátu je QR kód. Po jeho načtení stránka odpoví, jestli je doklad platný, propadlý, nebo jestli s ním někdo hnul.
Technická poznámka
Certifikát nese otisk SHA-256 spočítaný z údajů v okamžiku vydání. Zpětná změna jména nebo data se pozná, protože otisk přestane sedět. Každé ověření se loguje.
Fakturační údaje se vyplňují jednou pro všechno
IČO, DIČ a adresa žijí u centrálního účtu, ne v každé aplikaci zvlášť. Zákazník je opraví na jednom místě a projeví se to všude, i na faktuře.
Technická poznámka
Přihlašovací server je vydává rovnou jako součást přihlášení, takže se nemusí nic dosynchronizovávat. Nákupy pořízené bez přihlášení se po pozdější registraci k účtu přiřadí podle e-mailu, aby o ně zákazník nepřišel.
Jedna aplikace obsluhuje tři domény
Podle adresy, na kterou návštěvník přišel, se přepne režim webu a pustí jen odpovídající část. Šetří to provoz i údržbu.
Technická poznámka
Rozhodnutí padne v jednom souboru před vykreslením stránky. Tentýž soubor řeší i ochranu proti odeslání formuláře z cizí domény a oprávnění rolí, takže se pravidla nerozutečou po aplikaci.
Statistiky se počítají z účetních dat, ne z měřicího skriptu
Tržby, průměrná objednávka, ziskovost produktů, platební mix, heatmapa objednávek podle dne a hodiny. Vše se srovnává s předchozím stejně dlouhým obdobím.
Technická poznámka
Čísla se čtou přímo z tabulek objednávek a plateb, takže odpovídají tomu, co je na faktuře. Měřicí skript v prohlížeči umí čísla ztratit blokovaným požadavkem, databáze ne.
Provoz se hlídá sám
Třicet osm automatických úloh: párování plateb, upomínky, obnovy předplatných, opuštěné košíky, expirace licencí, doručování webhooků.
Technická poznámka
Záloha databáze běží denně, ověřuje se čtením zálohy zpátky a počítá kontrolní součet. Existuje i skript na cvičnou obnovu, protože záloha, kterou nikdo nikdy neobnovil, není záloha.
Bonusy nad rámec
4 funkcePráce navíc, která se nepočítala
Databáze rizik zdarma jako vstupní brána
Sedm set devadesát jedna pracovních nebezpečí ve veřejné encyklopedii, každé na vlastní adrese. Zdarma, bez registrace, a je to jeden z nejsilnějších zdrojů návštěvnosti.
Technická poznámka
Ke katalogu patří skoro pět tisíc předpřipravených opatření a sto čtyřicet pět profesí s vazbami na rizika. Placená verze z toho staví registr rizik pro konkrétní firmu, takže obsah zdarma a produkt sdílejí jedna data.
Sedm samostatných produktů s předplatným
Registr rizik, kniha návštěv, kniha úrazů, kalkulačky hluku a vibrací, generátor promptů, digitální dokumenty, inzertní portál. Každý se prodává sám a má vlastní obnovu.
Technická poznámka
Opakované platby mají u každého modulu stejný návrh: mandát, pokusy o stržení s upomínkami a doklad souhlasu včetně IP adresy, času a znění podmínek. Bez toho se souhlas se strháváním neobhájí.
Inzertní portál pro obor
Pět typů inzerátů: firma poptává, firma nabírá, odborník nabízí kapacitu, odborník hledá práci, dodavatel hledá zákazníky. S moderací před zveřejněním.
Technická poznámka
Odborník má pět reakcí měsíčně zdarma. Bezplatná úroveň není ukázka, ale funkční nástroj, protože prázdný inzertní portál nemá cenu pro nikoho.
Zákazník si postaví vlastní kurz
Firma může v editoru vytvořit vlastní školení nad vlastním obsahem a rozdat ho svým lidem. Platí se za rozsah, ne za každého uživatele zvlášť.
Technická poznámka
Rozsah se skládá z kreditů, slotů na kurzy a slotů na lekce. Firma tak platí za to, co opravdu potřebuje, místo aby přeskočila o celý tarif výš kvůli jedné lekci navíc.
Z čeho je to postavené a proč
Next.js
Stránky se skládají na serveru, takže prohlížeč dostane hotové HTML. U webu, který stojí na vyhledávačích a má přes tři tisíce adres, to není volba stylu.
React
Interaktivní části (přehrávač kurzu, košík, editor dokumentů) potřebují stav v prohlížeči. Zbytek webu zůstává serverový.
TypeScript
Čtyři sta tisíc řádků se bez typů neudrží. Sestavení padá na typové chybě, takže se rozbitá varianta na produkci neobjeví.
Tailwind CSS
Barvy, rádiusy a časování mají jediné místo pravdy v bloku @theme. Světlý i tmavý režim se pak přepíná přepsáním tokenů, ne druhou sadou komponent.
Prisma
Tři sta modelů a sto padesát devět migrací se spravuje z jednoho schématu. Migrace jsou verzované v gitu, takže je vidět, kdy a proč se datový model změnil.
PostgreSQL
Peníze potřebují transakce a unikátní indexy. Deduplikaci plateb tady řeší částečný unikátní index v databázi, ne podmínka v aplikaci, kterou by souběh obešel.
Docker a Caddy
Aplikace, databáze a migrátor běží jako tři služby v uzavřené síti. Ven nevede žádný port, veškerý provoz jde přes Caddy.
Caddy
Certifikáty se obnovují samy a hlavičky (HSTS, potlačení otisku serveru) jsou v jednom souboru. Při výpadku aplikace vrací vlastní stránku místo chyby brány.
S3 úložiště
Zakoupené soubory a fotodokumentace úrazů leží mimo aplikaci. Stahují se přes podepsanou adresu s krátkou platností, takže nasazení nikdy nepřepíše data zákazníků.
Jak to vypadá
Co si z toho odnést
- Od zadání ke spuštění
- 4 měsíce
- Co se dodalo
- Web na míru, E-shop, Aplikace na míru, Správa a rozvoj, SEO a obsah
- Web běží od
- 2026
- 20kroků objednávky bez ručního zásahu
- 3systémy, které si povídají samy
- 3 625adres na jednom webu
- 655lekcí v osmi kurzech
- 119 + 825blogových článků a videí
- 303tabulek v jedné databázi
Potřebujete něco podobného
Napište nám, co řešíte. Ozveme se do jednoho pracovního dne a řekneme rovnou, jestli to umíme a co to bude stát.

