V každém malém týmu, ve kterém jsem pracoval, se volno evidovalo ve sdílené tabulce. Žádná z nich ale nikdy neodpověděla na otázku, která lidi opravdu zajímá.
Ta otázka je vždycky stejná: kdo má příští týden volno? Na její zodpovězení tabulka nestačí. Data v ní jsou statická: drží dny, které si někdo zapsal, a nic s nimi nedělá — žádná žádost, žádné schválení, žádná připomínka, žádná kontrola, že nejsou dva lidé pryč ve stejném týdnu. Každé volno se musí domluvit osobně, a to stojí čas oba dva.
Nástroje, které tohle řeší pořádně, jsou stavěné pro HR oddělení. Chtějí organizační strukturu, napojení na mzdy a smlouvu na počet uživatelů dřív, než si pětičlenný tým stihne vzít volný pátek.
flexiday sedí přesně v téhle mezeře. Je to klidný sdílený kalendář pro týmy od několika lidí po několik stovek: žádost během pár vteřin, schválení jedním kliknutím, celý měsíc na jeden pohled. Zůstatky, státní svátky i kalendářové feedy si hlídá sám a nic z toho nepotřebuje HR oddělení.
Všechno visí na jednom kalendáři. Zbytek existuje proto, aby ten kalendář vždycky seděl.
Sdílený týmový kalendář
Jeden barevně odlišený pohled na to, kdo má kdy volno. Přepnete mezi vlastními záznamy a celou skupinou, vyfiltrujete podle typu volna a kliknutím na kterýkoli den odtud rovnou založíte žádost.
Devět druhů volna
Dovolená, home office, sick days, nemocenská, placené i neplacené volno, studijní volno, státní svátky a jedna univerzální položka. Kvótu ubírají jen první tři; ostatní tam jsou proto, aby kalendář říkal pravdu.
Schvalování na jedno kliknutí
Žádost přistane ve frontě schvalovatele i s termíny, typem a poznámkou. Schválit nebo zamítnout se dá jedním ťuknutím. Žadatel tak jako tak dostane e-mail a notifikaci v aplikaci, a při zamítnutí i důvod.
Každá změna stavu se ukládá jako událost, takže historie žádosti není nikdy záhada.
Kdo je pryč, na jeden pohled
Dashboard odpovídá na každodenní otázku dřív, než ji někdo stihne položit: kdo je dnes pryč, kdo bude pryč jako další a co čeká na mě. Hned vedle jsou zůstatky, takže manažer při schvalování rovnou vidí, jestli na to dny vůbec jsou.
Skupiny, schvalovatelé a pokrytí
Tým, pobočka nebo projekt — to všechno je skupina. Každá skupina má vlastního manažera, schvalovatele, pracovní dny a zemi, podle které se řídí svátky, takže kolega v Praze i kolega ve Vídni vidí každý ty správné červené dny.
Pokrytí je otázka, na kterou odpovídá pohled na skupinu: schvalovatel před schválením vidí, kdo další ze skupiny už v daných dnech chybí, takže se na slabý týden přijde dopředu, a ne až v něm.
Pozvánky jsou jednorázové odkazy vázané na e-mailovou adresu. Manažer může spravovat kalendář člena týmu, když si někdo zapomene zadat vlastní sick day.
Zůstatky, které sedí
Roční nároky, převod nevyčerpaných dnů i benefit sick days v placených tarifech se sledují na člověka a na skupinu. Naplánovaná úloha překlopí kvóty do nového roku. Report se exportuje do Excelu pro každého, kdo tabulku pořád ještě potřebuje.
Žije ve vašem vlastním kalendáři
Soukromý ICS feed dostane nepřítomnosti týmu do Google kalendáře, Outlooku nebo Apple kalendáře hned vedle vašich schůzek. Žádný plugin, žádné potvrzování OAuth; jednou se přihlásíte k odběru a dál se to udržuje samo.
Žádost za pár vteřin, na jakékoli obrazovce
Vyberete typ, vyberete rozsah, přidáte poznámku, hotovo. Vícedenní žádosti zůstávají pohromadě, takže schvalovatel vidí jednu položku, ne pět. V placených tarifech může žádost nést přílohu, třeba potvrzení od lékaře, která se nahraje rovnou do S3 a zpracuje ji Lambda.
Soukromé ve výchozím nastavení
Členové vidí svou skupinu. Schvalovatelé vidí to, co schvalují. Citlivé typy volna se všem kromě lidí, kteří to potřebují vědět, zobrazují diskrétně. Přihlášení podporuje Google, Microsoft a dvoufaktorové ověření.
Státní svátky podle země
Každá skupina si zvolí zemi, jejíž svátky sleduje, a pracovní dny, které se počítají. Svátky se dohledávají podle země a roku, takže nikdo neudržuje seznam červených dnů ručně a rozsah, který přes svátek přechází, potichu neubere den z něčího nároku.
Angličtina a čeština
Rozhraní, e-maily i veřejný web vycházejí v obou jazycích a volba jde za člověkem, ne za týmem. Řídí se jí i formát data, začátek týdne a názvy svátků, na čemž záleží víc než na samotném znění textů.
Webová aplikace, API a e-mailové šablony se verzují a nasazují každé podle svého.
Webová aplikace je statický export. Next.js ji sestaví do obyčejných souborů, které leží na S3 za CloudFrontem. Žádný serverový runtime, žádné route handlery, žádný middleware. Všechno dynamické je JSON volání na API, díky čemuž je hosting levný a útočná plocha malá.
API používá Express 5 na App Runneru s přísně jednosměrným vrstvením: routy volají controllery, controllery volají services a services sahají do databáze přes Drizzle. Kontroly oprávnění bydlí ve vrstvě services, takže na ně routa nemůže zapomenout. Cron úlohy ve stejném procesu překlápějí kvóty na přelomu roku a uklízejí prošlé přílohy.
E-maily se kompilují, nerenderují. Repozitář emails vykreslí react-email komponenty do HTML už při buildu a publikuje je do SES jako nativní šablony. API pak odesílá podle názvu šablony a s hrstkou proměnných. Rozbitá šablona shodí build e-mailů, nikdy ne požadavek uživatele.
Infrastruktura je Terraform: App Runner, RDS, VPC, S3, Secrets Manager, IAM a Route 53. Aplikování změn je vědomý ruční krok, nikdy nic, co by CI udělalo po zeleném buildu.
Repozitáře
- Web appDaniel88dev/flexi-dayNext.js SPA se statickým exportem: úvodní stránka a přihlášená část produktu.
- BackendDaniel88dev/flexi-day-beExpress 5 API, úlohy na pozadí a Terraform pro AWS.
- EmailsDaniel88dev/flexi-day-emailsŠablony react-email vykreslené při buildu a synchronizované do AWS SES.
- WorkspaceDaniel88dev/flexi-day-workspaceShell pro tři repozitáře: sdílené dovednosti agentů AI, lokální vývojářské CLI, MCP server a dokumentace napříč repozitáři, takže testy a nástroje běží z jednoho místa. Jednoduché sourozenecké klony spíše než submoduly, takže každý repozitář je stále vydáván podle vlastního plánu.
Repozitář workspace existuje proto, že tři nezávislé repozitáře se stejně musí vyvíjet společně. Drží agent skills, které používám s Claude Code, CLI, které nastartuje celý stack a naplní ho realistickým týmem, MCP server nabízející stejné operace agentům, a dokumentaci, která dává smysl jen napříč všemi třemi. Produktové repozitáře v něm leží jako obyčejné sesterské klony, a to záměrně: submoduly připnou konkrétní commit, a připínání je pravý opak toho, co nezávisle vydávané repozitáře potřebují.
Web app
- Next.js 16
- React 19
- TypeScript
- Tailwind v4
- shadcn/ui
- TanStack Query
- better-auth
- Zod
- Recharts
- Paddle
- S3 + CloudFront
- Vitest
- Sentry
Backend
- Node 24
- Express 5
- Drizzle ORM
- PostgreSQL
- better-auth
- Google OAuth
- Microsoft OAuth
- AWS SDK (SES, S3)
- App Runner
- RDS
- Lambda
- Terraform
- croner
- date-holidays
- ExcelJS
- sharp
- Vitest
- Sentry
Emails
- react-email
- React 19
- AWS SES templates
- tsx
Workspace
- Node scripts
- MCP server
- Claude agent skills
- GitHub Actions
- CodeQL
- actionlint
- shellcheck
- ESLint
- Prettier
Běží v ostrém provozu a pro první uživatele je zdarma.
flexiday běží na adrese flexi-day.com na infrastruktuře popsané výše. Platby stojí na Paddle jako merchant of record; tarify Free, Pro a Enterprise se liší tím, kolik skupin a lidí unesou. První uživatelé ho mají zdarma, dokud se produkt neusadí.
Provozuji ho jako OSVČ z Brna. Začalo to jako tabulka na evidenci dovolených, kterou jsem pořád rozbíjel, a dneska je z toho nástroj, jaký jsem si přál.
Co bude dál
- Přímá synchronizace s Google CalendaremZapisovat schválené volno rovnou do kalendářů lidí místo ICS feedu, který si dnes přidávají k odběru.
- Mobilní aplikaceNativní aplikace na dvě věci, které lidé na telefonu opravdu dělají: zadat si volno a schválit ho někomu jinému.
- 01
Statický frontend je přednost
Odstranění serveru z webové aplikace donutilo všechnu logiku bydlet na jednom místě, v API. Frontend je díky tomu levný na hosting a nemá odkud vynést tajemství, a poctivější je i lokální vývoj: co funguje proti localhost:8080, funguje i v produkci.
- 02
Kontroly oprávnění patří do vrstvy services
Zpočátku kontroly oprávnění bydlely v route handlerech a rozjížděly se. Jakmile se přesunuly vedle byznysové logiky, nový endpoint už je nemohl obejít a testy je mohly ověřovat bez HTTP.
- 03
E-mail je artefakt buildu
Vykreslení šablon při buildu a jejich synchronizace do SES proměnily e-mail z rizika za běhu v ověřený artefakt. Zástupné proměnné se kontrolují ještě před publikováním, takže šablona nemůže odejít s proměnnou, kterou nikdo nevyplní.
- 04
Naseedovat celý příběh, ne jeden řádek
Vývojářský příkaz, který vytvoří tým, kvóty a žádosti ve stavech pending, approved i rejected, udělal z každé obrazovky něco, co se dá vyzkoušet během pár vteřin. Snímky obrazovky na této stránce pocházejí právě z těchto dat.
- 05
Agenti potřebují sdílený workspace
Práce napříč třemi repozitáři s kódovacími agenty začala jít hladce až ve chvíli, kdy skills, vývojářské CLI a doménový slovník bydlely na jednom místě. Repozitář workspace je malý, a přesto z něj pochází většina užitku.