This commit is contained in:
Tomas Dvorak
2026-03-13 14:34:19 +01:00
parent 84a8acf944
commit 30d70a6aeb
126 changed files with 27297 additions and 29069 deletions
@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e469]: Mám zájem o ukázku MyClubu
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e469]: Mám zájem o ukázku MyClubu
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 594 KiB

@@ -0,0 +1,369 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- button "Otevřít navigaci" [ref=e12]:
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,369 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- button "Otevřít navigaci" [ref=e12]:
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

@@ -0,0 +1,458 @@
- generic:
- generic:
- generic:
- banner:
- generic:
- link:
- /url: "#top"
- generic: M
- generic:
- generic: MyClub
- generic: klubový web a provoz v jednom
- generic:
- button [expanded]:
- img
- main:
- generic:
- generic:
- generic:
- generic: MyClub SaaS pro sportovní kluby
- generic:
- heading [level=1]: Jeden systém pro web, obsah a provoz vašeho klubu.
- paragraph: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic:
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: MyUIbrix jako vestavěný editor homepage.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Připravené fungovat vedle stávajícího backendu a publikace.
- generic:
- generic:
- generic:
- generic:
- generic:
- paragraph: produktová ukázka
- generic: Řídicí vrstva pro klubový web
- generic: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic:
- generic:
- generic:
- generic:
- generic: homepage builder
- generic:
- generic:
- generic:
- generic:
- img
- text: Hero + novinky + zápasy
- generic: live preview
- generic:
- generic:
- generic: články
- generic: redakce
- generic:
- generic: partneři
- generic: bannery
- generic:
- generic: komunikace
- generic: newsletter
- generic:
- generic:
- img
- generic: Zápasy a tabulky v klubovém layoutu
- generic:
- img
- generic: Kontakty a newsletter bez externí skládačky
- generic:
- generic:
- generic:
- generic:
- img
- text: Match center
- generic: připraveno na víkend
- generic:
- generic:
- generic: 1. tým
- generic: sobota 16:30
- generic:
- generic: Dorost U19
- generic: neděle 10:15
- generic:
- generic: Ženy
- generic: neděle 14:00
- generic:
- generic:
- generic:
- img
- text: Přehled vedení
- img
- generic:
- generic:
- generic: obsah
- generic: pod kontrolou
- generic:
- generic: partneři
- generic: v publikaci
- generic:
- generic:
- generic:
- generic:
- generic:
- generic:
- img
- generic: Web + CMS
- generic: Jedno prostředí pro veřejný web i správu obsahu
- generic:
- paragraph: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic:
- generic:
- generic:
- img
- generic: Sportovní data
- generic: Zápasy, výsledky a tabulky v klubovém kontextu
- generic:
- paragraph: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic:
- generic:
- generic:
- img
- generic: Klubová agenda
- generic: Týmy, hráči, kontakty a role přehledně pohromadě
- generic:
- paragraph: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newsletter, kontaktní formuláře a engagement bez doplňků
- generic:
- paragraph: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic:
- generic:
- generic:
- img
- generic: Partneři
- generic: Sponzoři, bannery a promo plochy bez ručního chaosu
- generic:
- paragraph: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic:
- generic:
- generic:
- img
- generic: Přehled
- generic: Analytika a provozní kontrola v jednom dashboardu
- generic:
- paragraph: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic:
- generic:
- generic:
- generic: Platforma
- heading [level=2]: Navržené pro klub, který nechce skládat pět různých systémů.
- paragraph: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic:
- generic:
- generic:
- generic:
- img
- generic: MyUIbrix uvnitř
- generic: Skládání homepage bez front-end sprintu
- generic:
- paragraph: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic:
- generic:
- generic:
- img
- generic: Obsah
- generic: Redakce, články, galerie a videa v jednotném workflow
- generic:
- paragraph: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic:
- generic:
- generic:
- img
- generic: Matchday
- generic: Sportovní sekce, které nejsou jen statická tabulka
- generic:
- paragraph: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic:
- generic:
- generic:
- img
- generic: Marketing
- generic: Sponzoři, bannery a kampaně navázané na klubový obsah
- generic:
- paragraph: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- generic:
- paragraph: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic:
- generic:
- generic:
- img
- generic: Vedení klubu
- generic: Výsledky, aktivita a provozní signály na jednom místě
- generic:
- paragraph: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic:
- generic:
- generic:
- generic:
- generic: Ukázka produktu
- heading [level=2]: Editorial sports-tech bez generické šablony.
- paragraph: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic:
- generic:
- generic: ukázková kompozice
- generic: Homepage builder, který řídí rytmus celého klubu
- generic:
- generic:
- generic:
- generic: bloky stránky
- img
- generic:
- generic:
- generic: "01"
- generic: Hero s hlavní kampaní
- generic:
- generic: "02"
- generic: Novinky a články
- generic:
- generic: "03"
- generic: Příští zápas + tabulka
- generic:
- generic: "04"
- generic: Sponzoři a bannery
- generic:
- generic: "05"
- generic: Kontakty a mapa
- generic:
- generic:
- generic: preview
- img
- generic:
- generic:
- generic:
- generic:
- img
- generic: Pro management
- generic: Méně nástrojů, méně překlepů, méně ruční koordinace
- generic:
- paragraph: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic:
- generic:
- generic:
- img
- generic: Pro operativu
- generic: Rychlá reakce na zápasový víkend i změny v klubu
- generic:
- paragraph: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic:
- generic:
- generic:
- img
- generic: Pro obsahový tým
- generic: Média, články a vizuální skladba webu pod jednou střechou
- generic:
- paragraph: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic:
- generic:
- generic:
- generic: Jak to funguje
- heading [level=2]: Od první identity klubu po každodenní publikaci.
- paragraph: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic:
- generic:
- generic:
- generic:
- generic: krok 01
- generic: "01"
- generic: Nastavíte klubovou identitu
- generic:
- paragraph: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic:
- generic:
- generic:
- generic: krok 02
- generic: "02"
- generic: Poskládáte veřejný web v MyUIbrixu
- generic:
- paragraph: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic:
- generic:
- generic:
- generic: krok 03
- generic: "03"
- generic: Napojíte sportovní a obsahové vrstvy
- generic:
- paragraph: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic:
- generic:
- generic:
- generic: krok 04
- generic: "04"
- generic: Publikujete a dál ladíte provoz
- generic:
- paragraph: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic:
- generic:
- generic:
- generic: FAQ
- heading [level=2]: Krátké odpovědi na věci, které padnou nejdřív.
- paragraph: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic:
- generic:
- generic:
- generic:
- heading [level=3]:
- button:
- text: Je MyClub jen pro fotbalový klub?
- img
- generic:
- heading [level=3]:
- button:
- text: Musí každou změnu řešit vývojář?
- img
- generic:
- heading [level=3]:
- button:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- generic:
- heading [level=3]:
- button:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- generic:
- heading [level=3]:
- button:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic:
- generic:
- generic:
- generic:
- generic: CTA a poptávka
- generic:
- heading [level=2]: Chcete si projít, jak bude MyClub fungovat pro váš klub?
- paragraph: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic:
- generic:
- generic:
- img
- paragraph: Ukázka podle typu klubu a vašeho současného webu.
- generic:
- generic:
- img
- paragraph: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic:
- generic:
- img
- paragraph: Doporučení, jak navázat na stávající backend a publikaci.
- generic:
- generic:
- img
- text: Technická poznámka
- paragraph:
- text: V developmentu funguje formulář přes Vite proxy na
- code: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code: VITE_API_BASE_URL
- text: .
- generic:
- generic:
- generic: pracující formulář
- generic: Pošlete poptávku přes stávající backend
- generic:
- generic:
- generic:
- generic:
- generic: Jméno / klub
- textbox:
- /placeholder: Například FK Example / Jan Novák
- generic:
- generic: E-mail
- textbox:
- /placeholder: vas@email.cz
- generic:
- generic: Co chcete řešit
- textbox: Mám zájem o ukázku MyClubu
- generic:
- generic: Krátký kontext
- textbox:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic:
- button:
- text: Domluvit ukázku
- img
- paragraph:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code: VITE_API_BASE_URL
- text: .
- contentinfo:
- generic:
- generic:
- paragraph: MyClub
- paragraph: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- dialog "MyClub" [ref=e483]:
- generic [ref=e484]:
- heading "MyClub" [level=2] [ref=e485]
- paragraph [ref=e486]: Klubový web, obsah a provoz v jednom editoru.
- generic [ref=e487]:
- link "Platforma" [ref=e488] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e489] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e490] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e491] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e492] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e493] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- button "Close" [active] [ref=e494]:
- img
- generic [ref=e495]: Close
@@ -0,0 +1,458 @@
- generic:
- generic:
- generic:
- banner:
- generic:
- link:
- /url: "#top"
- generic: M
- generic:
- generic: MyClub
- generic: klubový web a provoz v jednom
- generic:
- button [expanded]:
- img
- main:
- generic:
- generic:
- generic:
- generic: MyClub SaaS pro sportovní kluby
- generic:
- heading [level=1]: Jeden systém pro web, obsah a provoz vašeho klubu.
- paragraph: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic:
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: MyUIbrix jako vestavěný editor homepage.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Připravené fungovat vedle stávajícího backendu a publikace.
- generic:
- generic:
- generic:
- generic:
- generic:
- paragraph: produktová ukázka
- generic: Řídicí vrstva pro klubový web
- generic: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic:
- generic:
- generic:
- generic:
- generic: homepage builder
- generic:
- generic:
- generic:
- generic:
- img
- text: Hero + novinky + zápasy
- generic: live preview
- generic:
- generic:
- generic: články
- generic: redakce
- generic:
- generic: partneři
- generic: bannery
- generic:
- generic: komunikace
- generic: newsletter
- generic:
- generic:
- img
- generic: Zápasy a tabulky v klubovém layoutu
- generic:
- img
- generic: Kontakty a newsletter bez externí skládačky
- generic:
- generic:
- generic:
- generic:
- img
- text: Match center
- generic: připraveno na víkend
- generic:
- generic:
- generic: 1. tým
- generic: sobota 16:30
- generic:
- generic: Dorost U19
- generic: neděle 10:15
- generic:
- generic: Ženy
- generic: neděle 14:00
- generic:
- generic:
- generic:
- img
- text: Přehled vedení
- img
- generic:
- generic:
- generic: obsah
- generic: pod kontrolou
- generic:
- generic: partneři
- generic: v publikaci
- generic:
- generic:
- generic:
- generic:
- generic:
- generic:
- img
- generic: Web + CMS
- generic: Jedno prostředí pro veřejný web i správu obsahu
- generic:
- paragraph: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic:
- generic:
- generic:
- img
- generic: Sportovní data
- generic: Zápasy, výsledky a tabulky v klubovém kontextu
- generic:
- paragraph: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic:
- generic:
- generic:
- img
- generic: Klubová agenda
- generic: Týmy, hráči, kontakty a role přehledně pohromadě
- generic:
- paragraph: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newsletter, kontaktní formuláře a engagement bez doplňků
- generic:
- paragraph: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic:
- generic:
- generic:
- img
- generic: Partneři
- generic: Sponzoři, bannery a promo plochy bez ručního chaosu
- generic:
- paragraph: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic:
- generic:
- generic:
- img
- generic: Přehled
- generic: Analytika a provozní kontrola v jednom dashboardu
- generic:
- paragraph: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic:
- generic:
- generic:
- generic: Platforma
- heading [level=2]: Navržené pro klub, který nechce skládat pět různých systémů.
- paragraph: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic:
- generic:
- generic:
- generic:
- img
- generic: MyUIbrix uvnitř
- generic: Skládání homepage bez front-end sprintu
- generic:
- paragraph: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic:
- generic:
- generic:
- img
- generic: Obsah
- generic: Redakce, články, galerie a videa v jednotném workflow
- generic:
- paragraph: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic:
- generic:
- generic:
- img
- generic: Matchday
- generic: Sportovní sekce, které nejsou jen statická tabulka
- generic:
- paragraph: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic:
- generic:
- generic:
- img
- generic: Marketing
- generic: Sponzoři, bannery a kampaně navázané na klubový obsah
- generic:
- paragraph: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- generic:
- paragraph: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic:
- generic:
- generic:
- img
- generic: Vedení klubu
- generic: Výsledky, aktivita a provozní signály na jednom místě
- generic:
- paragraph: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic:
- generic:
- generic:
- generic:
- generic: Ukázka produktu
- heading [level=2]: Editorial sports-tech bez generické šablony.
- paragraph: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic:
- generic:
- generic: ukázková kompozice
- generic: Homepage builder, který řídí rytmus celého klubu
- generic:
- generic:
- generic:
- generic: bloky stránky
- img
- generic:
- generic:
- generic: "01"
- generic: Hero s hlavní kampaní
- generic:
- generic: "02"
- generic: Novinky a články
- generic:
- generic: "03"
- generic: Příští zápas + tabulka
- generic:
- generic: "04"
- generic: Sponzoři a bannery
- generic:
- generic: "05"
- generic: Kontakty a mapa
- generic:
- generic:
- generic: preview
- img
- generic:
- generic:
- generic:
- generic:
- img
- generic: Pro management
- generic: Méně nástrojů, méně překlepů, méně ruční koordinace
- generic:
- paragraph: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic:
- generic:
- generic:
- img
- generic: Pro operativu
- generic: Rychlá reakce na zápasový víkend i změny v klubu
- generic:
- paragraph: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic:
- generic:
- generic:
- img
- generic: Pro obsahový tým
- generic: Média, články a vizuální skladba webu pod jednou střechou
- generic:
- paragraph: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic:
- generic:
- generic:
- generic: Jak to funguje
- heading [level=2]: Od první identity klubu po každodenní publikaci.
- paragraph: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic:
- generic:
- generic:
- generic:
- generic: krok 01
- generic: "01"
- generic: Nastavíte klubovou identitu
- generic:
- paragraph: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic:
- generic:
- generic:
- generic: krok 02
- generic: "02"
- generic: Poskládáte veřejný web v MyUIbrixu
- generic:
- paragraph: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic:
- generic:
- generic:
- generic: krok 03
- generic: "03"
- generic: Napojíte sportovní a obsahové vrstvy
- generic:
- paragraph: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic:
- generic:
- generic:
- generic: krok 04
- generic: "04"
- generic: Publikujete a dál ladíte provoz
- generic:
- paragraph: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic:
- generic:
- generic:
- generic: FAQ
- heading [level=2]: Krátké odpovědi na věci, které padnou nejdřív.
- paragraph: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic:
- generic:
- generic:
- generic:
- heading [level=3]:
- button:
- text: Je MyClub jen pro fotbalový klub?
- img
- generic:
- heading [level=3]:
- button:
- text: Musí každou změnu řešit vývojář?
- img
- generic:
- heading [level=3]:
- button:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- generic:
- heading [level=3]:
- button:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- generic:
- heading [level=3]:
- button:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic:
- generic:
- generic:
- generic:
- generic: CTA a poptávka
- generic:
- heading [level=2]: Chcete si projít, jak bude MyClub fungovat pro váš klub?
- paragraph: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic:
- generic:
- generic:
- img
- paragraph: Ukázka podle typu klubu a vašeho současného webu.
- generic:
- generic:
- img
- paragraph: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic:
- generic:
- img
- paragraph: Doporučení, jak navázat na stávající backend a publikaci.
- generic:
- generic:
- img
- text: Technická poznámka
- paragraph:
- text: V developmentu funguje formulář přes Vite proxy na
- code: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code: VITE_API_BASE_URL
- text: .
- generic:
- generic:
- generic: pracující formulář
- generic: Pošlete poptávku přes stávající backend
- generic:
- generic:
- generic:
- generic:
- generic: Jméno / klub
- textbox:
- /placeholder: Například FK Example / Jan Novák
- generic:
- generic: E-mail
- textbox:
- /placeholder: vas@email.cz
- generic:
- generic: Co chcete řešit
- textbox: Mám zájem o ukázku MyClubu
- generic:
- generic: Krátký kontext
- textbox:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic:
- button:
- text: Domluvit ukázku
- img
- paragraph:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code: VITE_API_BASE_URL
- text: .
- contentinfo:
- generic:
- generic:
- paragraph: MyClub
- paragraph: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- dialog "MyClub" [ref=e483]:
- generic [ref=e484]:
- heading "MyClub" [level=2] [ref=e485]
- paragraph [ref=e486]: Klubový web, obsah a provoz v jednom editoru.
- generic [ref=e487]:
- link "Platforma" [ref=e488] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e489] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e490] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e491] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e492] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e493] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- button "Close" [active] [ref=e494]:
- img
- generic [ref=e495]: Close
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,477 @@
- generic [active]:
- generic:
- generic:
- banner:
- generic:
- link:
- /url: "#top"
- generic: M
- generic:
- generic: MyClub
- generic: klubový web a provoz v jednom
- navigation:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main:
- generic:
- generic:
- generic:
- generic: MyClub SaaS pro sportovní kluby
- generic:
- heading [level=1]: Jeden systém pro web, obsah a provoz vašeho klubu.
- paragraph: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic:
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: MyUIbrix jako vestavěný editor homepage.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Připravené fungovat vedle stávajícího backendu a publikace.
- generic:
- generic:
- generic:
- generic:
- generic:
- paragraph: produktová ukázka
- generic: Řídicí vrstva pro klubový web
- generic: white mode only
- generic: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic:
- generic:
- generic:
- generic:
- generic: homepage builder
- generic:
- generic:
- generic:
- generic:
- img
- text: Hero + novinky + zápasy
- generic: live preview
- generic:
- generic:
- generic: články
- generic: redakce
- generic:
- generic: partneři
- generic: bannery
- generic:
- generic: komunikace
- generic: newsletter
- generic:
- generic:
- img
- generic: Zápasy a tabulky v klubovém layoutu
- generic:
- img
- generic: Kontakty a newsletter bez externí skládačky
- generic:
- generic:
- generic:
- generic:
- img
- text: Match center
- generic: připraveno na víkend
- generic:
- generic:
- generic: 1. tým
- generic: sobota 16:30
- generic:
- generic: Dorost U19
- generic: neděle 10:15
- generic:
- generic: Ženy
- generic: neděle 14:00
- generic:
- generic:
- generic:
- img
- text: Přehled vedení
- img
- generic:
- generic:
- generic: obsah
- generic: pod kontrolou
- generic:
- generic: partneři
- generic: v publikaci
- generic:
- generic:
- generic:
- generic:
- generic:
- generic:
- img
- generic: Web + CMS
- generic: Jedno prostředí pro veřejný web i správu obsahu
- generic:
- paragraph: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic:
- generic:
- generic:
- img
- generic: Sportovní data
- generic: Zápasy, výsledky a tabulky v klubovém kontextu
- generic:
- paragraph: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic:
- generic:
- generic:
- img
- generic: Klubová agenda
- generic: Týmy, hráči, kontakty a role přehledně pohromadě
- generic:
- paragraph: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newsletter, kontaktní formuláře a engagement bez doplňků
- generic:
- paragraph: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic:
- generic:
- generic:
- img
- generic: Partneři
- generic: Sponzoři, bannery a promo plochy bez ručního chaosu
- generic:
- paragraph: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic:
- generic:
- generic:
- img
- generic: Přehled
- generic: Analytika a provozní kontrola v jednom dashboardu
- generic:
- paragraph: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic:
- generic:
- generic:
- generic: Platforma
- heading [level=2]: Navržené pro klub, který nechce skládat pět různých systémů.
- paragraph: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic:
- generic:
- generic:
- generic:
- img
- generic: MyUIbrix uvnitř
- generic: Skládání homepage bez front-end sprintu
- generic:
- paragraph: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic:
- generic:
- generic:
- img
- generic: Obsah
- generic: Redakce, články, galerie a videa v jednotném workflow
- generic:
- paragraph: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic:
- generic:
- generic:
- img
- generic: Matchday
- generic: Sportovní sekce, které nejsou jen statická tabulka
- generic:
- paragraph: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic:
- generic:
- generic:
- img
- generic: Marketing
- generic: Sponzoři, bannery a kampaně navázané na klubový obsah
- generic:
- paragraph: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- generic:
- paragraph: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic:
- generic:
- generic:
- img
- generic: Vedení klubu
- generic: Výsledky, aktivita a provozní signály na jednom místě
- generic:
- paragraph: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic:
- generic:
- generic:
- generic:
- generic: Ukázka produktu
- heading [level=2]: Editorial sports-tech bez generické šablony.
- paragraph: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic:
- generic:
- generic: ukázková kompozice
- generic: Homepage builder, který řídí rytmus celého klubu
- generic:
- generic:
- generic:
- generic: bloky stránky
- img
- generic:
- generic:
- generic: "01"
- generic: Hero s hlavní kampaní
- generic:
- generic: "02"
- generic: Novinky a články
- generic:
- generic: "03"
- generic: Příští zápas + tabulka
- generic:
- generic: "04"
- generic: Sponzoři a bannery
- generic:
- generic: "05"
- generic: Kontakty a mapa
- generic:
- generic:
- generic: preview
- img
- generic:
- generic:
- generic:
- generic:
- img
- generic: Pro management
- generic: Méně nástrojů, méně překlepů, méně ruční koordinace
- generic:
- paragraph: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic:
- generic:
- generic:
- img
- generic: Pro operativu
- generic: Rychlá reakce na zápasový víkend i změny v klubu
- generic:
- paragraph: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic:
- generic:
- generic:
- img
- generic: Pro obsahový tým
- generic: Média, články a vizuální skladba webu pod jednou střechou
- generic:
- paragraph: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic:
- generic:
- generic:
- generic: Jak to funguje
- heading [level=2]: Od první identity klubu po každodenní publikaci.
- paragraph: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic:
- generic:
- generic:
- generic:
- generic: krok 01
- generic: "01"
- generic: Nastavíte klubovou identitu
- generic:
- paragraph: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic:
- generic:
- generic:
- generic: krok 02
- generic: "02"
- generic: Poskládáte veřejný web v MyUIbrixu
- generic:
- paragraph: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic:
- generic:
- generic:
- generic: krok 03
- generic: "03"
- generic: Napojíte sportovní a obsahové vrstvy
- generic:
- paragraph: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic:
- generic:
- generic:
- generic: krok 04
- generic: "04"
- generic: Publikujete a dál ladíte provoz
- generic:
- paragraph: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic:
- generic:
- generic:
- generic: FAQ
- heading [level=2]: Krátké odpovědi na věci, které padnou nejdřív.
- paragraph: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic:
- generic:
- generic:
- generic:
- heading [level=3]:
- button:
- text: Je MyClub jen pro fotbalový klub?
- img
- generic:
- heading [level=3]:
- button:
- text: Musí každou změnu řešit vývojář?
- img
- generic:
- heading [level=3]:
- button:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- generic:
- heading [level=3]:
- button:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- generic:
- heading [level=3]:
- button:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic:
- generic:
- generic:
- generic:
- generic: CTA a poptávka
- generic:
- heading [level=2]: Chcete si projít, jak bude MyClub fungovat pro váš klub?
- paragraph: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic:
- generic:
- generic:
- img
- paragraph: Ukázka podle typu klubu a vašeho současného webu.
- generic:
- generic:
- img
- paragraph: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic:
- generic:
- img
- paragraph: Doporučení, jak navázat na stávající backend a publikaci.
- generic:
- generic:
- img
- text: Technická poznámka
- paragraph:
- text: V developmentu funguje formulář přes Vite proxy na
- code: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code: VITE_API_BASE_URL
- text: .
- generic:
- generic:
- generic: pracující formulář
- generic: Pošlete poptávku přes stávající backend
- generic:
- generic:
- generic:
- generic:
- generic: Jméno / klub
- textbox:
- /placeholder: Například FK Example / Jan Novák
- generic:
- generic: E-mail
- textbox:
- /placeholder: vas@email.cz
- generic:
- generic: Co chcete řešit
- textbox: Mám zájem o ukázku MyClubu
- generic:
- generic: Krátký kontext
- textbox:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic:
- button:
- text: Domluvit ukázku
- img
- paragraph:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code: VITE_API_BASE_URL
- text: .
- contentinfo:
- generic:
- generic:
- paragraph: MyClub
- paragraph: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- dialog "MyClub" [ref=e483]:
- generic [ref=e484]:
- heading "MyClub" [level=2] [ref=e485]
- paragraph [ref=e486]: Klubový web, obsah a provoz v jednom editoru.
- generic [ref=e487]:
- link "Platforma" [ref=e488] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e489] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e490] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e491] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e492] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e493] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- button "Close" [ref=e494]:
- img
- generic [ref=e495]: Close
@@ -0,0 +1,477 @@
- generic [active]:
- generic:
- generic:
- banner:
- generic:
- link:
- /url: "#top"
- generic: M
- generic:
- generic: MyClub
- generic: klubový web a provoz v jednom
- navigation:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main:
- generic:
- generic:
- generic:
- generic: MyClub SaaS pro sportovní kluby
- generic:
- heading [level=1]: Jeden systém pro web, obsah a provoz vašeho klubu.
- paragraph: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic:
- link:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic:
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: MyUIbrix jako vestavěný editor homepage.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic:
- generic:
- img
- text: Přímý benefit
- paragraph: Připravené fungovat vedle stávajícího backendu a publikace.
- generic:
- generic:
- generic:
- generic:
- generic:
- paragraph: produktová ukázka
- generic: Řídicí vrstva pro klubový web
- generic: white mode only
- generic: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic:
- generic:
- generic:
- generic:
- generic: homepage builder
- generic:
- generic:
- generic:
- generic:
- img
- text: Hero + novinky + zápasy
- generic: live preview
- generic:
- generic:
- generic: články
- generic: redakce
- generic:
- generic: partneři
- generic: bannery
- generic:
- generic: komunikace
- generic: newsletter
- generic:
- generic:
- img
- generic: Zápasy a tabulky v klubovém layoutu
- generic:
- img
- generic: Kontakty a newsletter bez externí skládačky
- generic:
- generic:
- generic:
- generic:
- img
- text: Match center
- generic: připraveno na víkend
- generic:
- generic:
- generic: 1. tým
- generic: sobota 16:30
- generic:
- generic: Dorost U19
- generic: neděle 10:15
- generic:
- generic: Ženy
- generic: neděle 14:00
- generic:
- generic:
- generic:
- img
- text: Přehled vedení
- img
- generic:
- generic:
- generic: obsah
- generic: pod kontrolou
- generic:
- generic: partneři
- generic: v publikaci
- generic:
- generic:
- generic:
- generic:
- generic:
- generic:
- img
- generic: Web + CMS
- generic: Jedno prostředí pro veřejný web i správu obsahu
- generic:
- paragraph: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic:
- generic:
- generic:
- img
- generic: Sportovní data
- generic: Zápasy, výsledky a tabulky v klubovém kontextu
- generic:
- paragraph: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic:
- generic:
- generic:
- img
- generic: Klubová agenda
- generic: Týmy, hráči, kontakty a role přehledně pohromadě
- generic:
- paragraph: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newsletter, kontaktní formuláře a engagement bez doplňků
- generic:
- paragraph: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic:
- generic:
- generic:
- img
- generic: Partneři
- generic: Sponzoři, bannery a promo plochy bez ručního chaosu
- generic:
- paragraph: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic:
- generic:
- generic:
- img
- generic: Přehled
- generic: Analytika a provozní kontrola v jednom dashboardu
- generic:
- paragraph: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic:
- generic:
- generic:
- generic: Platforma
- heading [level=2]: Navržené pro klub, který nechce skládat pět různých systémů.
- paragraph: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic:
- generic:
- generic:
- generic:
- img
- generic: MyUIbrix uvnitř
- generic: Skládání homepage bez front-end sprintu
- generic:
- paragraph: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic:
- generic:
- generic:
- img
- generic: Obsah
- generic: Redakce, články, galerie a videa v jednotném workflow
- generic:
- paragraph: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic:
- generic:
- generic:
- img
- generic: Matchday
- generic: Sportovní sekce, které nejsou jen statická tabulka
- generic:
- paragraph: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic:
- generic:
- generic:
- img
- generic: Marketing
- generic: Sponzoři, bannery a kampaně navázané na klubový obsah
- generic:
- paragraph: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic:
- generic:
- generic:
- img
- generic: Komunikace
- generic: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- generic:
- paragraph: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic:
- generic:
- generic:
- img
- generic: Vedení klubu
- generic: Výsledky, aktivita a provozní signály na jednom místě
- generic:
- paragraph: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic:
- generic:
- generic:
- generic:
- generic: Ukázka produktu
- heading [level=2]: Editorial sports-tech bez generické šablony.
- paragraph: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic:
- generic:
- generic: ukázková kompozice
- generic: Homepage builder, který řídí rytmus celého klubu
- generic:
- generic:
- generic:
- generic: bloky stránky
- img
- generic:
- generic:
- generic: "01"
- generic: Hero s hlavní kampaní
- generic:
- generic: "02"
- generic: Novinky a články
- generic:
- generic: "03"
- generic: Příští zápas + tabulka
- generic:
- generic: "04"
- generic: Sponzoři a bannery
- generic:
- generic: "05"
- generic: Kontakty a mapa
- generic:
- generic:
- generic: preview
- img
- generic:
- generic:
- generic:
- generic:
- img
- generic: Pro management
- generic: Méně nástrojů, méně překlepů, méně ruční koordinace
- generic:
- paragraph: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic:
- generic:
- generic:
- img
- generic: Pro operativu
- generic: Rychlá reakce na zápasový víkend i změny v klubu
- generic:
- paragraph: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic:
- generic:
- generic:
- img
- generic: Pro obsahový tým
- generic: Média, články a vizuální skladba webu pod jednou střechou
- generic:
- paragraph: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic:
- generic:
- generic:
- generic: Jak to funguje
- heading [level=2]: Od první identity klubu po každodenní publikaci.
- paragraph: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic:
- generic:
- generic:
- generic:
- generic: krok 01
- generic: "01"
- generic: Nastavíte klubovou identitu
- generic:
- paragraph: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic:
- generic:
- generic:
- generic: krok 02
- generic: "02"
- generic: Poskládáte veřejný web v MyUIbrixu
- generic:
- paragraph: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic:
- generic:
- generic:
- generic: krok 03
- generic: "03"
- generic: Napojíte sportovní a obsahové vrstvy
- generic:
- paragraph: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic:
- generic:
- generic:
- generic: krok 04
- generic: "04"
- generic: Publikujete a dál ladíte provoz
- generic:
- paragraph: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic:
- generic:
- generic:
- generic: FAQ
- heading [level=2]: Krátké odpovědi na věci, které padnou nejdřív.
- paragraph: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic:
- generic:
- generic:
- generic:
- heading [level=3]:
- button:
- text: Je MyClub jen pro fotbalový klub?
- img
- generic:
- heading [level=3]:
- button:
- text: Musí každou změnu řešit vývojář?
- img
- generic:
- heading [level=3]:
- button:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- generic:
- heading [level=3]:
- button:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- generic:
- heading [level=3]:
- button:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic:
- generic:
- generic:
- generic:
- generic: CTA a poptávka
- generic:
- heading [level=2]: Chcete si projít, jak bude MyClub fungovat pro váš klub?
- paragraph: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic:
- generic:
- generic:
- img
- paragraph: Ukázka podle typu klubu a vašeho současného webu.
- generic:
- generic:
- img
- paragraph: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic:
- generic:
- img
- paragraph: Doporučení, jak navázat na stávající backend a publikaci.
- generic:
- generic:
- img
- text: Technická poznámka
- paragraph:
- text: V developmentu funguje formulář přes Vite proxy na
- code: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code: VITE_API_BASE_URL
- text: .
- generic:
- generic:
- generic: pracující formulář
- generic: Pošlete poptávku přes stávající backend
- generic:
- generic:
- generic:
- generic:
- generic: Jméno / klub
- textbox:
- /placeholder: Například FK Example / Jan Novák
- generic:
- generic: E-mail
- textbox:
- /placeholder: vas@email.cz
- generic:
- generic: Co chcete řešit
- textbox: Mám zájem o ukázku MyClubu
- generic:
- generic: Krátký kontext
- textbox:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic:
- button:
- text: Domluvit ukázku
- img
- paragraph:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code: VITE_API_BASE_URL
- text: .
- contentinfo:
- generic:
- generic:
- paragraph: MyClub
- paragraph: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic:
- link:
- /url: "#platforma"
- text: Platforma
- link:
- /url: "#ukazka"
- text: Ukázka
- link:
- /url: "#workflow"
- text: Jak to funguje
- link:
- /url: "#faq"
- text: FAQ
- link:
- /url: "#kontakt"
- text: Kontakt
- dialog "MyClub" [ref=e483]:
- generic [ref=e484]:
- heading "MyClub" [level=2] [ref=e485]
- paragraph [ref=e486]: Klubový web, obsah a provoz v jednom editoru.
- generic [ref=e487]:
- link "Platforma" [ref=e488] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e489] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e490] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e491] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e492] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e493] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- button "Close" [ref=e494]:
- img
- generic [ref=e495]: Close
Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

@@ -0,0 +1,387 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [active] [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- paragraph [ref=e505]: Zadejte prosím jméno nebo název klubu.
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- paragraph [ref=e506]: Zadejte prosím platný e-mail.
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- paragraph [ref=e507]: Doplňte prosím alespoň krátký kontext, co chcete řešit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,387 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [active] [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- paragraph [ref=e505]: Zadejte prosím jméno nebo název klubu.
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- paragraph [ref=e506]: Zadejte prosím platný e-mail.
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Mám zájem o ukázku MyClubu
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- paragraph [ref=e507]: Doplňte prosím alespoň krátký kontext, co chcete řešit.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

@@ -0,0 +1,388 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- text: FK Example
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- text: test@example.com
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Chci produktovou ukázku
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- paragraph [ref=e508]: Failed to save message
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,388 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- text: FK Example
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- text: test@example.com
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Chci produktovou ukázku
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- paragraph [ref=e508]: Failed to save message
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

@@ -0,0 +1,388 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- text: FK Example
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- text: test@example.com
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Chci produktovou ukázku
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- paragraph [ref=e508]: Failed to save message
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,388 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e496]:
- link "Platforma" [ref=e497] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e498] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e499] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e500] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e501] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e503] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e13]:
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: MyClub SaaS pro sportovní kluby
- generic [ref=e18]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e19]
- paragraph [ref=e20]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e21]:
- link "Domluvit ukázku" [ref=e22] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e23] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e24]:
- generic [ref=e25]:
- generic [ref=e26]:
- img [ref=e27]
- text: Přímý benefit
- paragraph [ref=e29]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e30]:
- generic [ref=e31]:
- img [ref=e32]
- text: Přímý benefit
- paragraph [ref=e34]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e35]:
- generic [ref=e36]:
- img [ref=e37]
- text: Přímý benefit
- paragraph [ref=e39]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e41]:
- generic [ref=e42]:
- generic [ref=e43]:
- generic [ref=e44]:
- paragraph [ref=e45]: produktová ukázka
- generic [ref=e46]: Řídicí vrstva pro klubový web
- generic [ref=e504]: white mode only
- generic [ref=e47]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- generic [ref=e56]: homepage builder
- generic [ref=e57]:
- generic [ref=e59]:
- generic [ref=e60]:
- img [ref=e61]
- text: Hero + novinky + zápasy
- generic [ref=e65]: live preview
- generic [ref=e73]:
- generic [ref=e74]:
- generic [ref=e75]: články
- generic [ref=e76]: redakce
- generic [ref=e77]:
- generic [ref=e78]: partneři
- generic [ref=e79]: bannery
- generic [ref=e80]:
- generic [ref=e81]: komunikace
- generic [ref=e82]: newsletter
- generic [ref=e83]:
- generic [ref=e84]:
- img [ref=e85]
- generic [ref=e87]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e88]:
- img [ref=e89]
- generic [ref=e92]: Kontakty a newsletter bez externí skládačky
- generic [ref=e93]:
- generic [ref=e94]:
- generic [ref=e95]:
- generic [ref=e96]:
- img [ref=e97]
- text: Match center
- generic [ref=e103]: připraveno na víkend
- generic [ref=e104]:
- generic [ref=e105]:
- generic [ref=e106]: 1. tým
- generic [ref=e107]: sobota 16:30
- generic [ref=e108]:
- generic [ref=e109]: Dorost U19
- generic [ref=e110]: neděle 10:15
- generic [ref=e111]:
- generic [ref=e112]: Ženy
- generic [ref=e113]: neděle 14:00
- generic [ref=e114]:
- generic [ref=e115]:
- generic [ref=e116]:
- img [ref=e117]
- text: Přehled vedení
- img [ref=e119]
- generic [ref=e122]:
- generic [ref=e123]:
- generic [ref=e124]: obsah
- generic [ref=e125]: pod kontrolou
- generic [ref=e126]:
- generic [ref=e127]: partneři
- generic [ref=e128]: v publikaci
- generic [ref=e131]:
- generic [ref=e132]:
- generic [ref=e133]:
- img [ref=e135]
- generic [ref=e138]: Web + CMS
- generic [ref=e139]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e141]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e142]:
- generic [ref=e143]:
- img [ref=e145]
- generic [ref=e151]: Sportovní data
- generic [ref=e152]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e154]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e155]:
- generic [ref=e156]:
- img [ref=e158]
- generic [ref=e162]: Klubová agenda
- generic [ref=e163]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e165]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e166]:
- generic [ref=e167]:
- img [ref=e169]
- generic [ref=e172]: Komunikace
- generic [ref=e173]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e175]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e176]:
- generic [ref=e177]:
- img [ref=e179]
- generic [ref=e182]: Partneři
- generic [ref=e183]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e185]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e186]:
- generic [ref=e187]:
- img [ref=e189]
- generic [ref=e191]: Přehled
- generic [ref=e192]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e194]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e196]:
- generic [ref=e197]:
- generic [ref=e198]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e199]
- paragraph [ref=e200]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e201]:
- generic [ref=e202]:
- generic [ref=e203]:
- img [ref=e205]
- generic [ref=e208]: MyUIbrix uvnitř
- generic [ref=e209]: Skládání homepage bez front-end sprintu
- paragraph [ref=e211]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e212]:
- generic [ref=e213]:
- img [ref=e215]
- generic [ref=e218]: Obsah
- generic [ref=e219]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e221]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e222]:
- generic [ref=e223]:
- img [ref=e225]
- generic [ref=e231]: Matchday
- generic [ref=e232]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e234]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e235]:
- generic [ref=e236]:
- img [ref=e238]
- generic [ref=e241]: Marketing
- generic [ref=e242]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e244]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e245]:
- generic [ref=e246]:
- img [ref=e248]
- generic [ref=e251]: Komunikace
- generic [ref=e252]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e254]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e255]:
- generic [ref=e256]:
- img [ref=e258]
- generic [ref=e260]: Vedení klubu
- generic [ref=e261]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e263]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e265]:
- generic [ref=e266]:
- generic [ref=e267]:
- generic [ref=e268]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e269]
- paragraph [ref=e270]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e271]:
- generic [ref=e272]:
- generic [ref=e273]: ukázková kompozice
- generic [ref=e274]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e275]:
- generic [ref=e276]:
- generic [ref=e277]:
- generic [ref=e278]: bloky stránky
- img [ref=e279]
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]: "01"
- generic [ref=e285]: Hero s hlavní kampaní
- generic [ref=e286]:
- generic [ref=e287]: "02"
- generic [ref=e288]: Novinky a články
- generic [ref=e289]:
- generic [ref=e290]: "03"
- generic [ref=e291]: Příští zápas + tabulka
- generic [ref=e292]:
- generic [ref=e293]: "04"
- generic [ref=e294]: Sponzoři a bannery
- generic [ref=e295]:
- generic [ref=e296]: "05"
- generic [ref=e297]: Kontakty a mapa
- generic [ref=e299]:
- generic [ref=e300]: preview
- img [ref=e301]
- generic [ref=e320]:
- generic [ref=e321]:
- generic [ref=e322]:
- img [ref=e324]
- generic [ref=e327]: Pro management
- generic [ref=e328]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e330]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e331]:
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Pro operativu
- generic [ref=e337]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e339]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e340]:
- generic [ref=e341]:
- img [ref=e343]
- generic [ref=e348]: Pro obsahový tým
- generic [ref=e349]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e351]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e353]:
- generic [ref=e354]:
- generic [ref=e355]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e356]
- paragraph [ref=e357]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e358]:
- generic [ref=e359]:
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: krok 01
- generic [ref=e363]: "01"
- generic [ref=e364]: Nastavíte klubovou identitu
- paragraph [ref=e366]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]:
- generic [ref=e370]: krok 02
- generic [ref=e371]: "02"
- generic [ref=e372]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e374]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]:
- generic [ref=e378]: krok 03
- generic [ref=e379]: "03"
- generic [ref=e380]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e382]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]:
- generic [ref=e386]: krok 04
- generic [ref=e387]: "04"
- generic [ref=e388]: Publikujete a dál ladíte provoz
- paragraph [ref=e390]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e392]:
- generic [ref=e393]:
- generic [ref=e394]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e395]
- paragraph [ref=e396]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e399]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e401]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e402]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e404]:
- button "Musí každou změnu řešit vývojář?" [ref=e405]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e407]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e408]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e410]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e411]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e413]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e414]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e417]:
- generic [ref=e418]:
- generic [ref=e419]: CTA a poptávka
- generic [ref=e420]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e421]
- paragraph [ref=e422]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e423]:
- generic [ref=e424]:
- img [ref=e426]
- paragraph [ref=e428]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e429]:
- img [ref=e431]
- paragraph [ref=e433]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e434]:
- img [ref=e436]
- paragraph [ref=e438]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e439]:
- generic [ref=e440]:
- img [ref=e441]
- text: Technická poznámka
- paragraph [ref=e444]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e445]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e446]: VITE_API_BASE_URL
- text: .
- generic [ref=e447]:
- generic [ref=e448]:
- generic [ref=e449]: pracující formulář
- generic [ref=e450]: Pošlete poptávku přes stávající backend
- generic [ref=e452]:
- generic [ref=e453]:
- generic [ref=e454]:
- generic [ref=e455]: Jméno / klub
- textbox "Jméno / klub" [ref=e456]:
- /placeholder: Například FK Example / Jan Novák
- text: FK Example
- generic [ref=e457]:
- generic [ref=e458]: E-mail
- textbox "E-mail" [ref=e459]:
- /placeholder: vas@email.cz
- text: test@example.com
- generic [ref=e460]:
- generic [ref=e461]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e462]: Chci produktovou ukázku
- generic [ref=e463]:
- generic [ref=e464]: Krátký kontext
- textbox "Krátký kontext" [ref=e465]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e466]:
- button "Domluvit ukázku" [ref=e467]:
- text: Domluvit ukázku
- img
- paragraph [ref=e468]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e469]: VITE_API_BASE_URL
- text: .
- paragraph [ref=e509]: Failed to save message
- contentinfo [ref=e471]:
- generic [ref=e472]:
- generic [ref=e473]:
- paragraph [ref=e474]: MyClub
- paragraph [ref=e475]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e476]:
- link "Platforma" [ref=e477] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e478] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e479] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e480] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e481] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e469]: Mám zájem o ukázku MyClubu
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,384 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e469]: Mám zájem o ukázku MyClubu
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
@@ -0,0 +1,386 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- text: Chci produktovou ukázku
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [active] [ref=e469]: Mám zájem o ukázku MyClubu
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

@@ -0,0 +1,388 @@
- generic [ref=e3]:
- banner [ref=e4]:
- generic [ref=e5]:
- link "M MyClub klubový web a provoz v jednom" [ref=e6] [cursor=pointer]:
- /url: "#top"
- generic [ref=e7]: M
- generic [ref=e8]:
- generic [ref=e9]: MyClub
- generic [ref=e10]: klubový web a provoz v jednom
- navigation [ref=e11]:
- link "Platforma" [ref=e12] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e13] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e14] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e15] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: "#kontakt"
- link "Domluvit ukázku" [ref=e18] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- main [ref=e19]:
- generic [ref=e21]:
- generic [ref=e22]:
- generic [ref=e23]: MyClub SaaS pro sportovní kluby
- generic [ref=e24]:
- heading "Jeden systém pro web, obsah a provoz vašeho klubu." [level=1] [ref=e25]
- paragraph [ref=e26]: MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
- generic [ref=e27]:
- link "Domluvit ukázku" [ref=e28] [cursor=pointer]:
- /url: "#kontakt"
- text: Domluvit ukázku
- img
- link "Projít produktovou vrstvu" [ref=e29] [cursor=pointer]:
- /url: "#ukazka"
- text: Projít produktovou vrstvu
- img
- generic [ref=e30]:
- generic [ref=e31]:
- generic [ref=e32]:
- img [ref=e33]
- text: Přímý benefit
- paragraph [ref=e35]: MyUIbrix jako vestavěný editor homepage.
- generic [ref=e36]:
- generic [ref=e37]:
- img [ref=e38]
- text: Přímý benefit
- paragraph [ref=e40]: Klubová data, obsah a komunikace bez pluginové skládačky.
- generic [ref=e41]:
- generic [ref=e42]:
- img [ref=e43]
- text: Přímý benefit
- paragraph [ref=e45]: Připravené fungovat vedle stávajícího backendu a publikace.
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]:
- generic [ref=e50]:
- paragraph [ref=e51]: produktová ukázka
- generic [ref=e52]: Řídicí vrstva pro klubový web
- generic [ref=e53]: white mode only
- generic [ref=e54]: MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
- generic [ref=e55]:
- generic [ref=e56]:
- generic [ref=e57]:
- generic [ref=e63]: homepage builder
- generic [ref=e64]:
- generic [ref=e66]:
- generic [ref=e67]:
- img [ref=e68]
- text: Hero + novinky + zápasy
- generic [ref=e72]: live preview
- generic [ref=e80]:
- generic [ref=e81]:
- generic [ref=e82]: články
- generic [ref=e83]: redakce
- generic [ref=e84]:
- generic [ref=e85]: partneři
- generic [ref=e86]: bannery
- generic [ref=e87]:
- generic [ref=e88]: komunikace
- generic [ref=e89]: newsletter
- generic [ref=e90]:
- generic [ref=e91]:
- img [ref=e92]
- generic [ref=e94]: Zápasy a tabulky v klubovém layoutu
- generic [ref=e95]:
- img [ref=e96]
- generic [ref=e99]: Kontakty a newsletter bez externí skládačky
- generic [ref=e100]:
- generic [ref=e101]:
- generic [ref=e102]:
- generic [ref=e103]:
- img [ref=e104]
- text: Match center
- generic [ref=e110]: připraveno na víkend
- generic [ref=e111]:
- generic [ref=e112]:
- generic [ref=e113]: 1. tým
- generic [ref=e114]: sobota 16:30
- generic [ref=e115]:
- generic [ref=e116]: Dorost U19
- generic [ref=e117]: neděle 10:15
- generic [ref=e118]:
- generic [ref=e119]: Ženy
- generic [ref=e120]: neděle 14:00
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]:
- img [ref=e124]
- text: Přehled vedení
- img [ref=e126]
- generic [ref=e129]:
- generic [ref=e130]:
- generic [ref=e131]: obsah
- generic [ref=e132]: pod kontrolou
- generic [ref=e133]:
- generic [ref=e134]: partneři
- generic [ref=e135]: v publikaci
- generic [ref=e138]:
- generic [ref=e139]:
- generic [ref=e140]:
- img [ref=e142]
- generic [ref=e145]: Web + CMS
- generic [ref=e146]: Jedno prostředí pro veřejný web i správu obsahu
- paragraph [ref=e148]: Stránky, články, galerie, bannery a homepage builder bez přepínání mezi nástroji.
- generic [ref=e149]:
- generic [ref=e150]:
- img [ref=e152]
- generic [ref=e158]: Sportovní data
- generic [ref=e159]: Zápasy, výsledky a tabulky v klubovém kontextu
- paragraph [ref=e161]: Připravené pro klubový provoz, včetně hráčů, týmů, rozpisů a matchday obsahu.
- generic [ref=e162]:
- generic [ref=e163]:
- img [ref=e165]
- generic [ref=e169]: Klubová agenda
- generic [ref=e170]: Týmy, hráči, kontakty a role přehledně pohromadě
- paragraph [ref=e172]: Obsahový tým, vedení klubu i operativa pracují nad jedním zdrojem pravdy.
- generic [ref=e173]:
- generic [ref=e174]:
- img [ref=e176]
- generic [ref=e179]: Komunikace
- generic [ref=e180]: Newsletter, kontaktní formuláře a engagement bez doplňků
- paragraph [ref=e182]: Komunikace s fanoušky, členy a partnery vychází přímo z klubového obsahu.
- generic [ref=e183]:
- generic [ref=e184]:
- img [ref=e186]
- generic [ref=e189]: Partneři
- generic [ref=e190]: Sponzoři, bannery a promo plochy bez ručního chaosu
- paragraph [ref=e192]: Klubová monetizace se řídí stejně snadno jako redakční obsah.
- generic [ref=e193]:
- generic [ref=e194]:
- img [ref=e196]
- generic [ref=e198]: Přehled
- generic [ref=e199]: Analytika a provozní kontrola v jednom dashboardu
- paragraph [ref=e201]: Vidíte, co klub publikuje, co funguje a co má smysl dál posílit.
- generic [ref=e203]:
- generic [ref=e204]:
- generic [ref=e205]: Platforma
- heading "Navržené pro klub, který nechce skládat pět různých systémů." [level=2] [ref=e206]
- paragraph [ref=e207]: Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack.
- generic [ref=e208]:
- generic [ref=e209]:
- generic [ref=e210]:
- img [ref=e212]
- generic [ref=e215]: MyUIbrix uvnitř
- generic [ref=e216]: Skládání homepage bez front-end sprintu
- paragraph [ref=e218]: Hero sekce, novinky, zápasy, bannery, kontakty i další bloky poskládáte vizuálně a s okamžitým náhledem.
- generic [ref=e219]:
- generic [ref=e220]:
- img [ref=e222]
- generic [ref=e225]: Obsah
- generic [ref=e226]: Redakce, články, galerie a videa v jednotném workflow
- paragraph [ref=e228]: Klubový obsah má společná média, kategorie, vyhledávání i publikaci napříč veřejným webem.
- generic [ref=e229]:
- generic [ref=e230]:
- img [ref=e232]
- generic [ref=e238]: Matchday
- generic [ref=e239]: Sportovní sekce, které nejsou jen statická tabulka
- paragraph [ref=e241]: Matches, standings, hráči a soutěže vypadají jako součást produktu, ne jako externí widget.
- generic [ref=e242]:
- generic [ref=e243]:
- img [ref=e245]
- generic [ref=e248]: Marketing
- generic [ref=e249]: Sponzoři, bannery a kampaně navázané na klubový obsah
- paragraph [ref=e251]: Promo plochy i partnerské sekce spravujete ve stejném systému jako články a homepage.
- generic [ref=e252]:
- generic [ref=e253]:
- img [ref=e255]
- generic [ref=e258]: Komunikace
- generic [ref=e259]: Newslettery, kontakty, komentáře a ankety bez lepení pluginů
- paragraph [ref=e261]: Fan engagement a klubové formuláře jsou součást platformy, ne další externí vrstva.
- generic [ref=e262]:
- generic [ref=e263]:
- img [ref=e265]
- generic [ref=e267]: Vedení klubu
- generic [ref=e268]: Výsledky, aktivita a provozní signály na jednom místě
- paragraph [ref=e270]: Obsah, návštěvnost a klubová agenda zůstávají čitelné i pro tým, který nechce složitou enterprise správu.
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]:
- generic [ref=e275]: Ukázka produktu
- heading "Editorial sports-tech bez generické šablony." [level=2] [ref=e276]
- paragraph [ref=e277]: Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu.
- generic [ref=e278]:
- generic [ref=e279]:
- generic [ref=e280]: ukázková kompozice
- generic [ref=e281]: Homepage builder, který řídí rytmus celého klubu
- generic [ref=e282]:
- generic [ref=e283]:
- generic [ref=e284]:
- generic [ref=e285]: bloky stránky
- img [ref=e286]
- generic [ref=e289]:
- generic [ref=e290]:
- generic [ref=e291]: "01"
- generic [ref=e292]: Hero s hlavní kampaní
- generic [ref=e293]:
- generic [ref=e294]: "02"
- generic [ref=e295]: Novinky a články
- generic [ref=e296]:
- generic [ref=e297]: "03"
- generic [ref=e298]: Příští zápas + tabulka
- generic [ref=e299]:
- generic [ref=e300]: "04"
- generic [ref=e301]: Sponzoři a bannery
- generic [ref=e302]:
- generic [ref=e303]: "05"
- generic [ref=e304]: Kontakty a mapa
- generic [ref=e306]:
- generic [ref=e307]: preview
- img [ref=e308]
- generic [ref=e327]:
- generic [ref=e328]:
- generic [ref=e329]:
- img [ref=e331]
- generic [ref=e334]: Pro management
- generic [ref=e335]: Méně nástrojů, méně překlepů, méně ruční koordinace
- paragraph [ref=e337]: Jedna platforma pro veřejný web, provozní data i komunikaci s partnery a komunitou.
- generic [ref=e338]:
- generic [ref=e339]:
- img [ref=e341]
- generic [ref=e343]: Pro operativu
- generic [ref=e344]: Rychlá reakce na zápasový víkend i změny v klubu
- paragraph [ref=e346]: Obsah, bannery, kontakty a homepage bloky upravíte bez čekání na nový deploy celé prezentace.
- generic [ref=e347]:
- generic [ref=e348]:
- img [ref=e350]
- generic [ref=e355]: Pro obsahový tým
- generic [ref=e356]: Média, články a vizuální skladba webu pod jednou střechou
- paragraph [ref=e358]: Redaktor i admin pracují nad stejným systémem a neřeší, kam co ručně kopírovat.
- generic [ref=e360]:
- generic [ref=e361]:
- generic [ref=e362]: Jak to funguje
- heading "Od první identity klubu po každodenní publikaci." [level=2] [ref=e363]
- paragraph [ref=e364]: Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu.
- generic [ref=e365]:
- generic [ref=e366]:
- generic [ref=e367]:
- generic [ref=e368]:
- generic [ref=e369]: krok 01
- generic [ref=e370]: "01"
- generic [ref=e371]: Nastavíte klubovou identitu
- paragraph [ref=e373]: Barvy, navigaci, kontakty, role, mapu a základní klubový obsah připravíte bez ohýbání obecného CMS.
- generic [ref=e374]:
- generic [ref=e375]:
- generic [ref=e376]:
- generic [ref=e377]: krok 02
- generic [ref=e378]: "02"
- generic [ref=e379]: Poskládáte veřejný web v MyUIbrixu
- paragraph [ref=e381]: Homepage builder drží vzhled webu pod kontrolou i ve chvíli, kdy potřebujete rychle změnit pořadí bloků a akcenty.
- generic [ref=e382]:
- generic [ref=e383]:
- generic [ref=e384]:
- generic [ref=e385]: krok 03
- generic [ref=e386]: "03"
- generic [ref=e387]: Napojíte sportovní a obsahové vrstvy
- paragraph [ref=e389]: Zprávy, zápasy, tabulky, hráče, partnery i newsletter propojujete v jednom toku práce.
- generic [ref=e390]:
- generic [ref=e391]:
- generic [ref=e392]:
- generic [ref=e393]: krok 04
- generic [ref=e394]: "04"
- generic [ref=e395]: Publikujete a dál ladíte provoz
- paragraph [ref=e397]: Obsahový tým publikuje, vedení sleduje přehled a klub má jednu platformu připravenou pro další růst.
- generic [ref=e399]:
- generic [ref=e400]:
- generic [ref=e401]: FAQ
- heading "Krátké odpovědi na věci, které padnou nejdřív." [level=2] [ref=e402]
- paragraph [ref=e403]: Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení.
- generic [ref=e406]:
- heading "Je MyClub jen pro fotbalový klub?" [level=3] [ref=e408]:
- button "Je MyClub jen pro fotbalový klub?" [ref=e409]:
- text: Je MyClub jen pro fotbalový klub?
- img
- heading "Musí každou změnu řešit vývojář?" [level=3] [ref=e411]:
- button "Musí každou změnu řešit vývojář?" [ref=e412]:
- text: Musí každou změnu řešit vývojář?
- img
- heading "Co všechno v landingu myslíte pojmem provoz klubu?" [level=3] [ref=e414]:
- button "Co všechno v landingu myslíte pojmem provoz klubu?" [ref=e415]:
- text: Co všechno v landingu myslíte pojmem provoz klubu?
- img
- heading "Dá se MyClub nasadit vedle stávajícího backendu?" [level=3] [ref=e417]:
- button "Dá se MyClub nasadit vedle stávajícího backendu?" [ref=e418]:
- text: Dá se MyClub nasadit vedle stávajícího backendu?
- img
- heading "Jak vypadá první krok po odeslání formuláře?" [level=3] [ref=e420]:
- button "Jak vypadá první krok po odeslání formuláře?" [ref=e421]:
- text: Jak vypadá první krok po odeslání formuláře?
- img
- generic [ref=e424]:
- generic [ref=e425]:
- generic [ref=e426]: CTA a poptávka
- generic [ref=e427]:
- heading "Chcete si projít, jak bude MyClub fungovat pro váš klub?" [level=2] [ref=e428]
- paragraph [ref=e429]: Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová první publikovatelná vrstva bez dalších backend zásahů.
- generic [ref=e430]:
- generic [ref=e431]:
- img [ref=e433]
- paragraph [ref=e435]: Ukázka podle typu klubu a vašeho současného webu.
- generic [ref=e436]:
- img [ref=e438]
- paragraph [ref=e440]: Průchod obsahem, MyUIbrix builderem i provozní agendou.
- generic [ref=e441]:
- img [ref=e443]
- paragraph [ref=e445]: Doporučení, jak navázat na stávající backend a publikaci.
- generic [ref=e446]:
- generic [ref=e447]:
- img [ref=e448]
- text: Technická poznámka
- paragraph [ref=e451]:
- text: V developmentu funguje formulář přes Vite proxy na
- code [ref=e452]: localhost:8080
- text: . V produkci může zůstat same-origin nebo využít
- code [ref=e453]: VITE_API_BASE_URL
- text: .
- generic [ref=e454]:
- generic [ref=e455]:
- generic [ref=e456]: pracující formulář
- generic [ref=e457]: Pošlete poptávku přes stávající backend
- generic [ref=e459]:
- generic [ref=e460]:
- generic [ref=e461]:
- generic [ref=e462]: Jméno / klub
- textbox "Jméno / klub" [ref=e463]:
- /placeholder: Například FK Example / Jan Novák
- text: FK Example
- generic [ref=e464]:
- generic [ref=e465]: E-mail
- textbox "E-mail" [ref=e466]:
- /placeholder: vas@email.cz
- text: test@example.com
- generic [ref=e467]:
- generic [ref=e468]: Co chcete řešit
- textbox "Co chcete řešit" [ref=e469]: Chci produktovou ukázku
- generic [ref=e470]:
- generic [ref=e471]: Krátký kontext
- textbox "Krátký kontext" [ref=e472]:
- /placeholder: Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit.
- text: Zajímá mě, jak rychle umíme přepnout klubový web, obsah a zápasy do jednoho produktu.
- generic [ref=e473]:
- button "Domluvit ukázku" [ref=e474]:
- text: Domluvit ukázku
- img
- paragraph [ref=e475]:
- text: Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo nastavit
- code [ref=e476]: VITE_API_BASE_URL
- text: .
- paragraph [ref=e489]: Server zprávu přijal, ale nepodařilo se ji uložit. Zkontrolujte databázi a nastavení kontaktního formuláře na backendu.
- contentinfo [ref=e478]:
- generic [ref=e479]:
- generic [ref=e480]:
- paragraph [ref=e481]: MyClub
- paragraph [ref=e482]: Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
- generic [ref=e483]:
- link "Platforma" [ref=e484] [cursor=pointer]:
- /url: "#platforma"
- link "Ukázka" [ref=e485] [cursor=pointer]:
- /url: "#ukazka"
- link "Jak to funguje" [ref=e486] [cursor=pointer]:
- /url: "#workflow"
- link "FAQ" [ref=e487] [cursor=pointer]:
- /url: "#faq"
- link "Kontakt" [ref=e488] [cursor=pointer]:
- /url: "#kontakt"
Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

+12 -1
View File
@@ -47,7 +47,6 @@ class OfflineSyncService {
constructor() { constructor() {
this.initializeNetworkListener(); this.initializeNetworkListener();
this.loadSyncQueue(); this.loadSyncQueue();
this.startPeriodicSync();
} }
private initializeNetworkListener() { private initializeNetworkListener() {
@@ -61,6 +60,9 @@ class OfflineSyncService {
const stored = await AsyncStorage.getItem(SYNC_QUEUE_KEY); const stored = await AsyncStorage.getItem(SYNC_QUEUE_KEY);
if (stored) { if (stored) {
this.syncQueue = JSON.parse(stored); this.syncQueue = JSON.parse(stored);
if (this.syncQueue.length > 0) {
this.startPeriodicSync();
}
} }
} catch (error) { } catch (error) {
console.error('Failed to load sync queue:', error); console.error('Failed to load sync queue:', error);
@@ -76,6 +78,10 @@ class OfflineSyncService {
} }
private startPeriodicSync() { private startPeriodicSync() {
if (this.syncInterval) {
return;
}
// Try to sync every 30 seconds when online // Try to sync every 30 seconds when online
this.syncInterval = setInterval(() => { this.syncInterval = setInterval(() => {
if (this.isOnline && this.syncQueue.length > 0) { if (this.isOnline && this.syncQueue.length > 0) {
@@ -99,6 +105,7 @@ class OfflineSyncService {
}; };
this.syncQueue.push(syncItem); this.syncQueue.push(syncItem);
this.startPeriodicSync();
this.saveSyncQueue(); this.saveSyncQueue();
// Try to sync immediately if online // Try to sync immediately if online
@@ -135,6 +142,10 @@ class OfflineSyncService {
this.syncQueue = remainingItems; this.syncQueue = remainingItems;
this.saveSyncQueue(); this.saveSyncQueue();
if (this.syncQueue.length === 0) {
this.stopPeriodicSync();
}
} }
private async processSyncItem(item: SyncItem, api: any) { private async processSyncItem(item: SyncItem, api: any) {
+1
View File
@@ -0,0 +1 @@
[]
+1
View File
@@ -0,0 +1 @@
{"lastUpdated":"2026-03-13T11:35:34+01:00"}
+48
View File
@@ -0,0 +1,48 @@
{
"baseURL": "http://127.0.0.1:8080/api/v1",
"duration_ms": 97,
"endpoints": [
{
"path": "/events/upcoming",
"file": "events_upcoming.json",
"ok": false,
"error": "unexpected status 500"
},
{
"path": "/public/team-logo-overrides",
"file": "team_logo_overrides.json",
"ok": false,
"error": "unexpected status 500"
},
{
"path": "/competition-aliases",
"file": "competition_aliases.json",
"ok": false,
"error": "unexpected status 500"
},
{
"path": "/settings",
"file": "settings.json",
"ok": false,
"error": "unexpected status 500"
},
{
"path": "/seo",
"file": "seo.json",
"ok": true
},
{
"path": "/articles?page=1\u0026page_size=10\u0026published=true",
"file": "articles.json",
"ok": false,
"error": "unexpected status 500"
},
{
"path": "/sponsors",
"file": "sponsors.json",
"ok": false,
"error": "unexpected status 500"
}
],
"lastUpdated": "2026-03-13T11:35:34+01:00"
}
+1
View File
@@ -0,0 +1 @@
{"additional_meta":"","canonical_base_url":"","default_og_image_url":"","enable_indexing":false,"meta_keywords":"","site_description":"","site_title":"","twitter_handle":""}
+1
View File
@@ -0,0 +1 @@
{"etag":"","fetched_at":"2026-03-13T11:35:34+01:00","last_modified":""}
Binary file not shown.
@@ -0,0 +1,41 @@
package goosemigrations
import (
"context"
"database/sql"
"errors"
"fotbal-club/internal/dbschema"
"github.com/pressly/goose/v3"
"gorm.io/driver/postgres"
"gorm.io/gorm"
gormlogger "gorm.io/gorm/logger"
)
func init() {
goose.AddMigrationContext(upBootstrapLegacySchema, downBootstrapLegacySchema)
}
func upBootstrapLegacySchema(ctx context.Context, tx *sql.Tx) error {
if _, err := tx.ExecContext(ctx, `
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
`); err != nil {
return err
}
gormDB, err := gorm.Open(postgres.New(postgres.Config{Conn: tx}), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
Logger: gormlogger.Default.LogMode(gormlogger.Silent),
})
if err != nil {
return err
}
return dbschema.AutoMigrate(gormDB)
}
func downBootstrapLegacySchema(context.Context, *sql.Tx) error {
return errors.New("bootstrap schema migration is irreversible")
}
+51
View File
@@ -0,0 +1,51 @@
-- name: ListRecentOrderSummaries :many
SELECT
o.id,
o.order_number,
o.status,
o.total_amount_cents,
o.currency,
o.shipping_method,
o.shipping_price_cents,
o.created_at,
COALESCE(p.status, '') AS payment_status,
COALESCE(s.status, '') AS shipping_status
FROM eshop_orders AS o
LEFT JOIN LATERAL (
SELECT ep.status
FROM eshop_payments AS ep
WHERE ep.order_id = o.id
AND ep.deleted_at IS NULL
ORDER BY ep.created_at DESC
LIMIT 1
) AS p ON TRUE
LEFT JOIN LATERAL (
SELECT sl.status
FROM eshop_shipping_labels AS sl
WHERE sl.order_id = o.id
AND sl.deleted_at IS NULL
ORDER BY sl.created_at DESC
LIMIT 1
) AS s ON TRUE
WHERE o.deleted_at IS NULL
ORDER BY o.created_at DESC
LIMIT $1;
-- name: SummarizeOrderRevenue :one
SELECT
COUNT(*)::bigint AS order_count,
COALESCE(SUM(total_amount_cents), 0)::bigint AS gross_revenue_cents,
COALESCE(SUM(shipping_price_cents), 0)::bigint AS shipping_revenue_cents
FROM eshop_orders
WHERE deleted_at IS NULL
AND created_at >= $1
AND created_at < $2;
-- name: ListOrderStatusBreakdown :many
SELECT
status,
COUNT(*)::bigint AS order_count
FROM eshop_orders
WHERE deleted_at IS NULL
GROUP BY status
ORDER BY order_count DESC, status ASC;
@@ -0,0 +1,3 @@
CREATE TABLE users (
id SERIAL PRIMARY KEY
);
+3 -1
View File
@@ -51,7 +51,9 @@ func main() {
// Optional migrations for eshop-specific tables only (will be added later) // Optional migrations for eshop-specific tables only (will be added later)
runMigrations, _ := strconv.ParseBool(os.Getenv("RUN_MIGRATIONS")) runMigrations, _ := strconv.ParseBool(os.Getenv("RUN_MIGRATIONS"))
if runMigrations { if runMigrations {
log.Println("[eshop] RUN_MIGRATIONS is true, but no eshop-specific migrations are defined yet") if err := database.MigrateDB(dbInstance); err != nil {
log.Fatalf("[eshop] Failed to run database migrations: %v", err)
}
} }
// Initialize Gin router with a similar hardened stack as the main backend // Initialize Gin router with a similar hardened stack as the main backend
-3
View File
@@ -15,9 +15,6 @@ COPY . .
# Build app # Build app
ENV NODE_ENV=production ENV NODE_ENV=production
ENV GENERATE_SOURCEMAP=false
ENV CI=true
ENV TSC_COMPILE_ON_ERROR=true
RUN npm run build RUN npm run build
@@ -9,5 +9,6 @@
<body> <body>
<noscript>Pro zobrazení e-shopu je potřeba povolit JavaScript.</noscript> <noscript>Pro zobrazení e-shopu je potřeba povolit JavaScript.</noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body> </body>
</html> </html>
+1615 -14317
View File
File diff suppressed because it is too large Load Diff
+13 -8
View File
@@ -3,10 +3,11 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "react-scripts start", "start": "vite",
"build": "react-scripts build", "dev": "vite",
"test": "react-scripts test", "build": "vite build",
"eject": "react-scripts eject" "preview": "vite preview",
"test": "vitest run"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/react": "^2.8.2", "@chakra-ui/react": "^2.8.2",
@@ -15,18 +16,22 @@
"@stripe/react-stripe-js": "^5.4.1", "@stripe/react-stripe-js": "^5.4.1",
"@stripe/stripe-js": "^8.5.3", "@stripe/stripe-js": "^8.5.3",
"@tanstack/react-query": "^4.36.1", "@tanstack/react-query": "^4.36.1",
"axios": "^1.6.2", "axios": "^1.13.6",
"dompurify": "^3.3.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-router-dom": "^6.20.1", "react-router-dom": "^6.30.2",
"react-scripts": "5.0.1",
"typescript": "^4.9.5" "typescript": "^4.9.5"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.2.45", "@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"@types/react-router-dom": "^5.3.3" "@types/react-router-dom": "^5.3.3",
"@vitejs/plugin-react": "^4.4.1",
"jsdom": "^26.1.0",
"vite": "^6.3.5",
"vitest": "^3.1.1"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { getProduct, addToCart, EshopProductVariant } from '../services/eshopApi'; import { getProduct, addToCart, EshopProductVariant } from '../services/eshopApi';
import { Box, Heading, Text, Image, Badge, HStack, VStack, Button, Select, useToast } from '@chakra-ui/react'; import { Box, Heading, Text, Image, Badge, HStack, VStack, Button, Select, useToast } from '@chakra-ui/react';
import { sanitizeRichHtml } from '../utils/sanitizeHtml';
const formatPrice = (cents: number, currency: string) => { const formatPrice = (cents: number, currency: string) => {
const value = cents / 100; const value = cents / 100;
@@ -20,6 +21,7 @@ const ProductDetailPage: React.FC = () => {
enabled: !!slug, enabled: !!slug,
}); });
const [variantId, setVariantId] = useState<number | undefined>(undefined); const [variantId, setVariantId] = useState<number | undefined>(undefined);
const descriptionHtml = React.useMemo(() => sanitizeRichHtml(data?.description_html), [data?.description_html]);
if (isLoading) return <Text>Načítání produktu</Text>; if (isLoading) return <Text>Načítání produktu</Text>;
if (isError || !data) return <Text>Produkt nebyl nalezen.</Text>; if (isError || !data) return <Text>Produkt nebyl nalezen.</Text>;
@@ -76,9 +78,9 @@ const ProductDetailPage: React.FC = () => {
<Button colorScheme="blue" onClick={handleAddToCart} maxW="260px"> <Button colorScheme="blue" onClick={handleAddToCart} maxW="260px">
Přidat do košíku Přidat do košíku
</Button> </Button>
{data.description_html && ( {descriptionHtml && (
<Box mt={4} fontSize="sm" color="gray.700"> <Box mt={4} fontSize="sm" color="gray.700">
<div dangerouslySetInnerHTML={{ __html: data.description_html }} /> <div dangerouslySetInnerHTML={{ __html: descriptionHtml }} />
</Box> </Box>
)} )}
</VStack> </VStack>
+1 -1
View File
@@ -1 +1 @@
/// <reference types="react-scripts" /> /// <reference types="vite/client" />
+28
View File
@@ -0,0 +1,28 @@
import DOMPurify from 'dompurify';
const ADDITIONAL_TAGS = ['iframe'];
const ADDITIONAL_ATTRS = ['allow', 'allowfullscreen', 'class', 'rel', 'style', 'target'];
export function sanitizeRichHtml(html: string | null | undefined): string {
const sanitized = DOMPurify.sanitize(html ?? '', {
USE_PROFILES: { html: true },
ADD_TAGS: ADDITIONAL_TAGS,
ADD_ATTR: ADDITIONAL_ATTRS,
});
if (typeof window === 'undefined' || !sanitized) {
return sanitized;
}
const template = window.document.createElement('template');
template.innerHTML = sanitized;
template.content.querySelectorAll<HTMLAnchorElement>('a[target="_blank"]').forEach((anchor) => {
const rel = new Set((anchor.getAttribute('rel') ?? '').split(/\s+/).filter(Boolean));
rel.add('noopener');
rel.add('noreferrer');
anchor.setAttribute('rel', Array.from(rel).join(' '));
});
return template.innerHTML;
}
+1 -1
View File
@@ -15,7 +15,7 @@
"noEmit": true, "noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"baseUrl": "src", "baseUrl": "src",
"types": [] "types": ["vite/client", "vitest/globals"]
}, },
"include": ["src"] "include": ["src"]
} }
+58
View File
@@ -0,0 +1,58 @@
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
function buildProcessEnv(mode: string, env: Record<string, string>, base: string) {
const processEnv: Record<string, string> = {
NODE_ENV: mode === 'production' ? 'production' : mode,
PUBLIC_URL: base === '/' ? '' : base.replace(/\/$/, ''),
};
for (const [key, value] of Object.entries(env)) {
if (key.startsWith('REACT_APP_')) {
processEnv[key] = value;
}
}
return processEnv;
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const base = env.PUBLIC_URL ? (env.PUBLIC_URL.endsWith('/') ? env.PUBLIC_URL : `${env.PUBLIC_URL}/`) : '/';
const processEnv = buildProcessEnv(mode, env, base);
return {
base,
publicDir: 'public',
plugins: [react()],
define: {
'process.env': JSON.stringify(processEnv),
global: 'globalThis',
},
build: {
outDir: 'build',
assetsDir: 'static',
emptyOutDir: true,
sourcemap: false,
},
server: {
host: '0.0.0.0',
port: 3100,
proxy: {
'/api': {
target: 'http://127.0.0.1:8082',
changeOrigin: true,
secure: false,
},
},
},
preview: {
host: '0.0.0.0',
port: 4174,
},
test: {
environment: 'jsdom',
globals: true,
},
};
});
BIN
View File
Binary file not shown.
-20
View File
@@ -15,27 +15,7 @@ COPY . .
# Build the app with production settings # Build the app with production settings
ENV NODE_ENV=production ENV NODE_ENV=production
# Disable ESLint during build to avoid CRA/ESLint v9 plugin incompatibilities
ENV DISABLE_ESLINT_PLUGIN=true
# Skip CRA preflight checks (peer deps, eslint presence) to prevent extra work in CI builds
ENV SKIP_PREFLIGHT_CHECK=true
# Disable source maps to reduce memory usage
ENV GENERATE_SOURCEMAP=false
# Reduce memory footprint - Node.js in Docker needs more conservative settings
ENV NODE_OPTIONS="--max-old-space-size=1024" ENV NODE_OPTIONS="--max-old-space-size=1024"
# Limit webpack parallelism to reduce memory usage
ENV CI=true
# Allow build to continue even if TypeScript diagnostics exist; avoids heavy TS checks from blocking
ENV TSC_COMPILE_ON_ERROR=true
# Disable ForkTsCheckerWebpackPlugin via craco filter to further reduce memory
ENV DISABLE_TS_TYPECHECK=true
# Disable ESLint plugin completely
ENV ESLINT_NO_DEV_ERRORS=true
# Clean npm cache before build to free up memory
RUN npm cache clean --force 2>/dev/null || true
# Build with standard npm
RUN --mount=type=cache,target=/root/.npm \ RUN --mount=type=cache,target=/root/.npm \
npm run build npm run build
-68
View File
@@ -1,68 +0,0 @@
const path = require('path');
module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src/')
},
configure: (webpackConfig) => {
// Always remove ESLint for better performance
webpackConfig.plugins = (webpackConfig.plugins || []).filter((plugin) => {
const name = plugin && plugin.constructor && plugin.constructor.name;
if (name === 'ESLintWebpackPlugin') return false;
return true;
});
// Optimize for production builds
if (process.env.NODE_ENV === 'production') {
// Reduce memory usage during build
webpackConfig.optimization = {
...webpackConfig.optimization,
splitChunks: {
chunks: 'all',
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
// Use single runtime chunk
runtimeChunk: 'single',
};
// Limit parallelism of existing minimizers to lower memory footprint
if (Array.isArray(webpackConfig.optimization.minimizer)) {
webpackConfig.optimization.minimizer = webpackConfig.optimization.minimizer.map((minimizer) => {
const name = minimizer && minimizer.constructor && minimizer.constructor.name;
if (name === 'TerserPlugin') {
if (minimizer.options) {
minimizer.options.parallel = false;
minimizer.options.extractComments = false;
}
}
if (name === 'CssMinimizerPlugin' || name === 'CssMinimizerWebpackPlugin') {
if (minimizer.options) {
minimizer.options.parallel = 1;
}
}
return minimizer;
});
}
// Disable source maps if env variable is set
if (process.env.GENERATE_SOURCEMAP === 'false') {
webpackConfig.devtool = false;
}
}
return webpackConfig;
},
}
};
+28
View File
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="theme-color" content="#000000" />
<meta name="color-scheme" content="light dark" />
<meta
name="description"
content="Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie"
/>
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://www.youtube.com" crossorigin />
<link rel="preconnect" href="https://i.ytimg.com" crossorigin />
<link rel="preconnect" href="https://s.ytimg.com" crossorigin />
<link rel="preconnect" href="https://www.google.com" crossorigin />
<title>Fotbal Club</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
+1981 -13342
View File
File diff suppressed because it is too large Load Diff
+13 -14
View File
@@ -3,18 +3,15 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "craco start", "start": "vite",
"build": "craco build", "dev": "vite",
"test": "craco test", "build": "vite build",
"eject": "react-scripts eject", "preview": "vite preview",
"dev": "bun start", "test": "vitest run"
"dev:fast": "bun --hot start",
"build:bun": "bun run build"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.1.1", "@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.2", "@chakra-ui/react": "^2.8.2",
"@craco/craco": "^7.1.0",
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
@@ -26,15 +23,15 @@
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@tinymce/tinymce-react": "^6.3.0", "@tinymce/tinymce-react": "^6.3.0",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.2",
"@types/node": "^16.18.126", "@types/node": "^20.17.47",
"@types/qrcode": "^1.5.6", "@types/qrcode": "^1.5.6",
"@types/react": "^18.2.45", "@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"@types/react-frame-component": "^4.1.6", "@types/react-frame-component": "^4.1.6",
"axios": "^1.6.2", "axios": "^1.13.6",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"dompurify": "^3.2.6", "dompurify": "^3.3.0",
"framer-motion": "^10.16.4", "framer-motion": "^10.16.4",
"i18next": "^23.7.16", "i18next": "^23.7.16",
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
@@ -58,8 +55,7 @@
"react-image-crop": "^11.0.10", "react-image-crop": "^11.0.10",
"react-markdown": "^10.1.0", "react-markdown": "^10.1.0",
"react-quill": "^2.0.0", "react-quill": "^2.0.0",
"react-router-dom": "^6.20.1", "react-router-dom": "^6.30.2",
"react-scripts": "5.0.1",
"react-simple-maps": "^3.0.0", "react-simple-maps": "^3.0.0",
"react-syntax-highlighter": "^15.6.6", "react-syntax-highlighter": "^15.6.6",
"tinymce": "^8.2.2", "tinymce": "^8.2.2",
@@ -76,9 +72,12 @@
"@types/react-chartjs-2": "^2.0.2", "@types/react-chartjs-2": "^2.0.2",
"@types/react-image-crop": "^8.1.6", "@types/react-image-crop": "^8.1.6",
"@types/react-syntax-highlighter": "^15.5.13", "@types/react-syntax-highlighter": "^15.5.13",
"@vitejs/plugin-react": "^4.4.1",
"eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"http-proxy-middleware": "^3.0.5" "jsdom": "^26.1.0",
"vite": "^6.3.5",
"vitest": "^3.1.1"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
-55
View File
@@ -1,55 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- Club favicon/logo -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- Optional SVG logo if available in public folder (keeps ICO as fallback) -->
<!-- <link rel="icon" type="image/svg+xml" href="%PUBLIC_URL%/logo.svg" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="theme-color" content="#000000" />
<meta name="color-scheme" content="light dark" />
<meta
name="description"
content="Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!-- Performance: preconnect to Google Fonts origins used by the app -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- Performance: preconnect to YouTube origins for faster video/thumbnail loads -->
<link rel="preconnect" href="https://www.youtube.com" crossorigin />
<link rel="preconnect" href="https://i.ytimg.com" crossorigin />
<link rel="preconnect" href="https://s.ytimg.com" crossorigin />
<link rel="preconnect" href="https://www.google.com" crossorigin />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Fotbal Club</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
+2 -2
View File
@@ -1,11 +1,11 @@
import React, { lazy, Suspense } from 'react'; import React, { lazy, Suspense } from 'react';
import { ChakraProvider, extendTheme, Spinner, Center, Box } from '@chakra-ui/react'; import { ChakraProvider, Spinner, Center, Box } from '@chakra-ui/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom';
import { AuthProvider, useAuth } from './contexts/AuthContext'; import { AuthProvider, useAuth } from './contexts/AuthContext';
import { ClubThemeProvider } from './contexts/ClubThemeContext'; import { ClubThemeProvider } from './contexts/ClubThemeContext';
import { HelmetProvider } from 'react-helmet-async'; import { HelmetProvider } from 'react-helmet-async';
import { theme } from './App'; import { theme } from './theme/siteTheme';
import { useUmami } from './hooks/useUmami'; import { useUmami } from './hooks/useUmami';
import { useFontLoader } from './hooks/useFontLoader'; import { useFontLoader } from './hooks/useFontLoader';
import DefaultSEO from './components/seo/DefaultSEO'; import DefaultSEO from './components/seo/DefaultSEO';
+2 -154
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ChakraProvider, extendTheme } from '@chakra-ui/react'; import { ChakraProvider } from '@chakra-ui/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet, useLocation } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, Navigate, Outlet, useLocation } from 'react-router-dom';
import './styles/custom-scrollbar.css'; import './styles/custom-scrollbar.css';
@@ -94,6 +94,7 @@ import { useUmami } from './hooks/useUmami';
import { checkin } from './services/engagement'; import { checkin } from './services/engagement';
import { useFontLoader } from './hooks/useFontLoader'; import { useFontLoader } from './hooks/useFontLoader';
import { usePublicSettings } from './hooks/usePublicSettings'; import { usePublicSettings } from './hooks/usePublicSettings';
import { theme } from './theme/siteTheme';
import { logAction } from './services/actionLog'; import { logAction } from './services/actionLog';
const RouteLogger: React.FC = () => { const RouteLogger: React.FC = () => {
@@ -117,159 +118,6 @@ const queryClient = new QueryClient({
}, },
}); });
// Theme configuration drawing colors from ClubTheme CSS variables for personalization
export const theme = extendTheme({
config: {
initialColorMode: 'light',
useSystemColorMode: false,
},
// Provide a brand color scale so colorScheme="brand" components style correctly
colors: {
brand: {
50: '#e6f7ff',
100: '#b3e0ff',
200: '#80caff',
300: '#4db3ff',
400: '#1a9cff',
500: 'var(--club-primary, #0b5cff)',
600: '#0066cc',
700: '#004d99',
800: '#003366',
900: '#001a33',
},
},
// Semantic tokens allow live updates when ClubThemeContext changes CSS variables
semanticTokens: {
colors: {
'brand.primary': {
default: 'var(--club-primary, #0b5cff)',
},
'brand.secondary': {
default: 'var(--club-secondary, #ffd200)',
},
'brand.accent': {
default: 'var(--club-accent, #141414)',
},
'text.onPrimary': {
default: 'var(--club-text-on-primary, #ffffff)',
},
'bg.app': {
default: '#f8f9fb',
_dark: '#0f1115',
},
'text.app': {
default: '#1a1a1a',
_dark: '#e8eaf0',
},
// Backdrop/outline shades
'border.subtle': {
default: 'rgba(0,0,0,0.06)',
_dark: 'rgba(255,255,255,0.12)',
},
'bg.card': {
default: '#ffffff',
_dark: '#1a1d29',
},
'bg.elevated': {
default: '#ffffff',
_dark: '#242831',
},
},
},
styles: {
global: {
'html, body, #root': {
height: '100%',
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
body: {
bg: 'bg.app',
color: 'text.app',
lineHeight: 1.5,
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
'h1, h2, h3, h4, h5, h6': {
fontFamily: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
a: {
transition: 'color 0.2s ease',
},
'::selection': {
background: 'brand.accent',
color: 'black',
},
},
},
components: {
Container: {
baseStyle: {
px: { base: 4, md: 6 },
},
sizes: {
'7xl': '88rem',
},
},
Button: {
baseStyle: {
fontWeight: '700',
borderRadius: 'md',
letterSpacing: '0.4px',
_hover: { transform: 'translateY(-1px)', boxShadow: 'md' },
_active: { transform: 'translateY(0)' },
},
variants: {
solid: {
bg: 'brand.primary',
color: 'text.onPrimary',
_hover: { filter: 'brightness(0.95)' },
},
outline: {
border: '2px solid',
borderColor: 'brand.primary',
color: 'brand.primary',
_hover: { bg: 'rgba(0,0,0,0.02)' },
},
ghost: {
color: 'brand.secondary',
_hover: { bg: 'rgba(0,0,0,0.04)' },
},
},
},
Card: {
baseStyle: {
container: {
borderRadius: 'lg',
boxShadow: 'sm',
overflow: 'hidden',
transition: 'all 0.2s',
borderWidth: '1px',
borderColor: 'border.subtle',
_hover: { transform: 'translateY(-4px)', boxShadow: 'lg' },
},
},
},
Divider: {
baseStyle: {
borderColor: 'border.subtle',
},
},
Heading: {
baseStyle: {
fontFamily: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
},
Text: {
baseStyle: {
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
},
},
fonts: {
heading: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
body: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
});
// Component to initialize analytics inside Router context // Component to initialize analytics inside Router context
const AnalyticsInitializer: React.FC = () => { const AnalyticsInitializer: React.FC = () => {
useUmami(); useUmami();
@@ -6,6 +6,7 @@ import { useAuth } from '../../contexts/AuthContext';
import { Pencil, Trash2, Send, CheckCircle2 } from 'lucide-react'; import { Pencil, Trash2, Send, CheckCircle2 } from 'lucide-react';
import { Link as RouterLink } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { sanitizeRichHtml } from '../../utils/sanitizeHtml';
type Props = { type Props = {
targetType: 'article' | 'event' | 'gallery_album' | 'youtube_video'; targetType: 'article' | 'event' | 'gallery_album' | 'youtube_video';
@@ -382,7 +383,7 @@ const CommentsSection: React.FC<Props> = ({ targetType, targetId }) => {
</VStack> </VStack>
) : ( ) : (
c.content_html ? ( c.content_html ? (
<Box sx={{ '.cw': { textDecoration: 'underline dotted', cursor: 'help' } }} dangerouslySetInnerHTML={{ __html: c.content_html }} /> <Box sx={{ '.cw': { textDecoration: 'underline dotted', cursor: 'help' } }} dangerouslySetInnerHTML={{ __html: sanitizeRichHtml(c.content_html) }} />
) : ( ) : (
<Text whiteSpace="pre-wrap">{c.content}</Text> <Text whiteSpace="pre-wrap">{c.content}</Text>
) )
@@ -0,0 +1,44 @@
import React from 'react';
import { useCountdown } from '../../hooks/useCountdown';
const formatVerboseCountdown = (timeRemaining: number) => {
if (timeRemaining <= 0) {
return '';
}
const totalSeconds = Math.floor(timeRemaining / 1000);
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
return `${days} d ${hours} h ${minutes} m ${seconds} s`;
};
export const buildKickoffIso = (date?: string, time?: string) => {
if (!date) {
return null;
}
return `${date}T${(time || '00:00')}:00`;
};
const MatchCountdownText: React.FC<{
targetDate?: string | Date | null;
fallback?: string;
startedLabel?: string;
}> = ({ targetDate = null, fallback = '—', startedLabel = 'Začátek' }) => {
const { targetTime, timeRemaining } = useCountdown(targetDate, 1000);
if (!targetTime) {
return <>{fallback}</>;
}
if (timeRemaining <= 0) {
return <>{startedLabel}</>;
}
return <>{formatVerboseCountdown(timeRemaining)}</>;
};
export default React.memo(MatchCountdownText);
+213 -84
View File
@@ -130,6 +130,8 @@ interface ElementPosition {
height: number; height: number;
} }
type DragInsertPosition = 'before' | 'after';
const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onConfigChange }) => { const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onConfigChange }) => {
const { user } = useAuth(); const { user } = useAuth();
const isAdmin = user?.role === 'admin'; const isAdmin = user?.role === 'admin';
@@ -149,6 +151,7 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const [elementOrder, setElementOrder] = useState<string[]>([]); const [elementOrder, setElementOrder] = useState<string[]>([]);
const [draggedElement, setDraggedElement] = useState<string | null>(null); const [draggedElement, setDraggedElement] = useState<string | null>(null);
const [dragOverElement, setDragOverElement] = useState<string | null>(null); const [dragOverElement, setDragOverElement] = useState<string | null>(null);
const [dragOverPlacement, setDragOverPlacement] = useState<DragInsertPosition | null>(null);
const [viewport, setViewport] = useState<'desktop' | 'tablet' | 'mobile'>('desktop'); const [viewport, setViewport] = useState<'desktop' | 'tablet' | 'mobile'>('desktop');
const [elementStyles, setElementStyles] = useState<Record<string, any>>({}); const [elementStyles, setElementStyles] = useState<Record<string, any>>({});
const [showStylePanel, setShowStylePanel] = useState(false); const [showStylePanel, setShowStylePanel] = useState(false);
@@ -163,6 +166,7 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const [pendingInsertIndex, setPendingInsertIndex] = useState<number | null>(null); const [pendingInsertIndex, setPendingInsertIndex] = useState<number | null>(null);
const [containerGridCols, setContainerGridCols] = useState<number>(0); const [containerGridCols, setContainerGridCols] = useState<number>(0);
const elementOrderRef = useRef<string[]>([]); const elementOrderRef = useRef<string[]>([]);
const draggedElementRef = useRef<string | null>(null);
useEffect(() => { elementOrderRef.current = elementOrder; }, [elementOrder]); useEffect(() => { elementOrderRef.current = elementOrder; }, [elementOrder]);
const applyVisualReorderRef = useRef<(order: string[]) => void>(() => {}); const applyVisualReorderRef = useRef<(order: string[]) => void>(() => {});
@@ -221,6 +225,53 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
return getDefaultVariant(elementName); return getDefaultVariant(elementName);
}, [getAvailableVariants, getDefaultVariant]); }, [getAvailableVariants, getDefaultVariant]);
const getDropPlacement = useCallback((clientY: number, rect: Pick<DOMRect, 'top' | 'height'>): DragInsertPosition => {
return clientY < rect.top + (rect.height / 2) ? 'before' : 'after';
}, []);
const reorderElements = useCallback((
currentOrder: string[],
draggedName: string,
targetName: string,
placement: DragInsertPosition = 'before'
) => {
const draggedIndex = currentOrder.indexOf(draggedName);
const targetIndex = currentOrder.indexOf(targetName);
if (draggedIndex === -1 || targetIndex === -1 || draggedName === targetName) {
return currentOrder;
}
const nextOrder = [...currentOrder];
nextOrder.splice(draggedIndex, 1);
const adjustedTargetIndex = nextOrder.indexOf(targetName);
const insertionIndex = placement === 'after' ? adjustedTargetIndex + 1 : adjustedTargetIndex;
nextOrder.splice(Math.max(0, insertionIndex), 0, draggedName);
const unchanged = nextOrder.length === currentOrder.length && nextOrder.every((name, index) => name === currentOrder[index]);
return unchanged ? currentOrder : nextOrder;
}, []);
const resetDragState = useCallback(() => {
draggedElementRef.current = null;
setDraggedElement(null);
setDragOverElement(null);
setDragOverPlacement(null);
}, []);
const commitElementOrderChange = useCallback((nextOrder: string[]) => {
setElementOrder(nextOrder);
setHasChanges(true);
if (isEditing) {
requestAnimationFrame(() => {
applyVisualReorderRef.current(nextOrder);
window.dispatchEvent(new CustomEvent('myuibrix-reorder', {
detail: { order: nextOrder, previewMode: true }
}));
});
}
}, [isEditing]);
// Draggable panel handlers // Draggable panel handlers
const handlePanelMouseDown = useCallback((panelName: string, e: React.MouseEvent) => { const handlePanelMouseDown = useCallback((panelName: string, e: React.MouseEvent) => {
// Only allow dragging from header area // Only allow dragging from header area
@@ -681,6 +732,8 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const overlay = document.createElement('div'); const overlay = document.createElement('div');
overlay.className = 'elementor-overlay'; overlay.className = 'elementor-overlay';
overlay.dataset.elementName = elementName;
overlay.setAttribute('data-editor-overlay', elementName);
overlay.style.cssText = ` overlay.style.cssText = `
position: absolute; position: absolute;
top: 0; top: 0;
@@ -732,6 +785,31 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
pointer-events: auto; pointer-events: auto;
`; `;
const dragHandleBtn = document.createElement('button');
dragHandleBtn.textContent = '::';
dragHandleBtn.title = 'Přetáhnout pro změnu pořadí';
dragHandleBtn.setAttribute('aria-label', `Přetáhnout ${elementName}`);
dragHandleBtn.setAttribute('data-editor-drag-handle', elementName);
dragHandleBtn.style.cssText = `
background: ${secondaryColor};
color: ${clubTheme.textOnSecondary || 'white'};
border: none;
width: 32px;
height: 32px;
border-radius: 6px;
cursor: grab;
font-size: 14px;
font-weight: 800;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
transition: transform 0.2s;
`;
dragHandleBtn.draggable = true;
dragHandleBtn.onmouseover = () => dragHandleBtn.style.transform = 'scale(1.1)';
dragHandleBtn.onmouseout = () => dragHandleBtn.style.transform = 'scale(1)';
// Edit button // Edit button
const editBtn = document.createElement('button'); const editBtn = document.createElement('button');
editBtn.innerHTML = '⚙️'; editBtn.innerHTML = '⚙️';
@@ -842,6 +920,7 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
} }
// Use safeDOM to build overlay structure // Use safeDOM to build overlay structure
safeDOM.appendChild(actionsBar, dragHandleBtn);
safeDOM.appendChild(actionsBar, editBtn); safeDOM.appendChild(actionsBar, editBtn);
safeDOM.appendChild(actionsBar, moveUpBtn); safeDOM.appendChild(actionsBar, moveUpBtn);
safeDOM.appendChild(actionsBar, moveDownBtn); safeDOM.appendChild(actionsBar, moveDownBtn);
@@ -866,6 +945,24 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
return; return;
} }
const applyOverlayIdleState = () => {
overlay.style.boxShadow = '';
if (selectedElement !== elementName) {
overlay.style.border = `2px dashed ${primaryColor}`;
overlay.style.background = `${primaryColor}15`;
}
};
const applyOverlayDropIndicator = (placement: DragInsertPosition) => {
overlay.style.border = `3px solid ${secondaryColor}`;
overlay.style.background = `${secondaryColor}18`;
overlay.style.boxShadow = placement === 'before'
? `inset 0 4px 0 ${secondaryColor}`
: `inset 0 -4px 0 ${secondaryColor}`;
setDragOverElement(elementName);
setDragOverPlacement(placement);
};
// Click to auto-select and open style panel // Click to auto-select and open style panel
overlay.addEventListener('click', (e) => { overlay.addEventListener('click', (e) => {
// Don't trigger if clicking on action buttons // Don't trigger if clicking on action buttons
@@ -895,6 +992,7 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
overlay.addEventListener('mouseleave', () => { overlay.addEventListener('mouseleave', () => {
setHoveredElement(null); setHoveredElement(null);
overlay.style.boxShadow = '';
if (selectedElement !== elementName) { if (selectedElement !== elementName) {
overlay.style.border = '2px dashed transparent'; overlay.style.border = '2px dashed transparent';
overlay.style.background = 'transparent'; overlay.style.background = 'transparent';
@@ -958,57 +1056,77 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
// per-column insert handled by elementor-col-picker buttons above // per-column insert handled by elementor-col-picker buttons above
// Make overlay draggable dragHandleBtn.addEventListener('dragstart', (e) => {
overlay.draggable = true;
overlay.addEventListener('dragstart', (e) => {
e.stopPropagation(); e.stopPropagation();
try { (e as DragEvent).dataTransfer?.setData('text/plain', elementName); } catch {} try { (e as DragEvent).dataTransfer?.setData('text/plain', elementName); } catch {}
try {
if ((e as DragEvent).dataTransfer) {
(e as DragEvent).dataTransfer!.effectAllowed = 'move';
}
} catch {}
draggedElementRef.current = elementName;
setDraggedElement(elementName); setDraggedElement(elementName);
setDragOverElement(null);
setDragOverPlacement(null);
dragHandleBtn.style.cursor = 'grabbing';
overlay.style.opacity = '0.5'; overlay.style.opacity = '0.5';
}); });
overlay.addEventListener('dragend', (e) => { dragHandleBtn.addEventListener('dragend', (e) => {
e.stopPropagation(); e.stopPropagation();
dragHandleBtn.style.cursor = 'grab';
overlay.style.opacity = '1'; overlay.style.opacity = '1';
setDraggedElement(null); overlay.style.boxShadow = '';
resetDragState();
});
overlay.addEventListener('dragenter', (e) => {
e.preventDefault();
e.stopPropagation();
const activeDragged = draggedElementRef.current;
if (activeDragged && activeDragged !== elementName) {
const placement = getDropPlacement((e as DragEvent).clientY, overlay.getBoundingClientRect());
applyOverlayDropIndicator(placement);
}
}); });
overlay.addEventListener('dragover', (e) => { overlay.addEventListener('dragover', (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
try { (e as DragEvent).dataTransfer!.dropEffect = 'move'; } catch {} try { (e as DragEvent).dataTransfer!.dropEffect = 'move'; } catch {}
if (draggedElement && draggedElement !== elementName) { const activeDragged = draggedElementRef.current;
overlay.style.border = `3px solid ${secondaryColor}`; if (activeDragged && activeDragged !== elementName) {
setDragOverElement(elementName); const placement = getDropPlacement((e as DragEvent).clientY, overlay.getBoundingClientRect());
applyOverlayDropIndicator(placement);
} }
}); });
overlay.addEventListener('dragleave', (e) => { overlay.addEventListener('dragleave', (e) => {
e.stopPropagation(); e.stopPropagation();
if (selectedElement !== elementName) { const nextTarget = document.elementFromPoint((e as DragEvent).clientX, (e as DragEvent).clientY);
overlay.style.border = `2px dashed ${primaryColor}`; if (nextTarget && overlay.contains(nextTarget)) {
return;
} }
applyOverlayIdleState();
setDragOverElement(null); setDragOverElement(null);
setDragOverPlacement(null);
}); });
overlay.addEventListener('drop', (e) => { overlay.addEventListener('drop', (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (draggedElement && draggedElement !== elementName) { const activeDragged = draggedElementRef.current;
// Reorder elements if (activeDragged && activeDragged !== elementName) {
const newOrder = [...elementOrderRef.current]; const placement = dragOverPlacement || getDropPlacement((e as DragEvent).clientY, overlay.getBoundingClientRect());
const draggedIndex = newOrder.indexOf(draggedElement as string); const newOrder = reorderElements(elementOrderRef.current, activeDragged, elementName, placement);
const targetIndex = newOrder.indexOf(elementName);
if (draggedIndex !== -1 && targetIndex !== -1) { if (newOrder !== elementOrderRef.current) {
newOrder.splice(draggedIndex, 1); pushHistorySnapshot();
newOrder.splice(targetIndex, 0, draggedElement as string); commitElementOrderChange(newOrder);
setElementOrder(newOrder);
setHasChanges(true);
applyVisualReorderRef.current(newOrder);
} }
} }
overlay.style.border = `2px dashed ${primaryColor}`; applyOverlayIdleState();
resetDragState();
setDragOverElement(null); setDragOverElement(null);
}); });
}); });
@@ -1069,7 +1187,22 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
clearTimeout(debounceTimerRef.current); clearTimeout(debounceTimerRef.current);
} }
}; };
}, [isEditing, selectedElement, pageType, elementOrder, visibleElements]); }, [
isEditing,
selectedElement,
pageType,
elementOrder,
visibleElements,
containerGridCols,
primaryColor,
secondaryColor,
clubTheme.textOnSecondary,
getDropPlacement,
reorderElements,
resetDragState,
pushHistorySnapshot,
commitElementOrderChange,
]);
// Update selected element overlay styling // Update selected element overlay styling
useEffect(() => { useEffect(() => {
@@ -1425,17 +1558,8 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const newOrder = [...elementOrder]; const newOrder = [...elementOrder];
[newOrder[currentIndex - 1], newOrder[currentIndex]] = [newOrder[currentIndex], newOrder[currentIndex - 1]]; [newOrder[currentIndex - 1], newOrder[currentIndex]] = [newOrder[currentIndex], newOrder[currentIndex - 1]];
setElementOrder(newOrder); commitElementOrderChange(newOrder);
setHasChanges(true); }, [elementOrder, commitElementOrderChange, pushHistorySnapshot]);
// Trigger reorder event and apply visual reordering
if (isEditing) {
applyVisualReorder(newOrder);
window.dispatchEvent(new CustomEvent('myuibrix-reorder', {
detail: { order: newOrder, previewMode: true }
}));
}
}, [elementOrder, isEditing, applyVisualReorder]);
const handleMoveDown = useCallback((elementName: string) => { const handleMoveDown = useCallback((elementName: string) => {
pushHistorySnapshot(); pushHistorySnapshot();
@@ -1444,83 +1568,70 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const newOrder = [...elementOrder]; const newOrder = [...elementOrder];
[newOrder[currentIndex], newOrder[currentIndex + 1]] = [newOrder[currentIndex + 1], newOrder[currentIndex]]; [newOrder[currentIndex], newOrder[currentIndex + 1]] = [newOrder[currentIndex + 1], newOrder[currentIndex]];
setElementOrder(newOrder); commitElementOrderChange(newOrder);
setHasChanges(true); }, [elementOrder, commitElementOrderChange, pushHistorySnapshot]);
// Trigger reorder event and apply visual reordering
if (isEditing) {
applyVisualReorder(newOrder);
window.dispatchEvent(new CustomEvent('myuibrix-reorder', {
detail: { order: newOrder, previewMode: true }
}));
}
}, [elementOrder, isEditing, applyVisualReorder]);
// Drag and drop handlers with improved state management // Drag and drop handlers with improved state management
const handleDragStart = useCallback((elementName: string, e: React.DragEvent) => { const handleDragStart = useCallback((elementName: string, e: React.DragEvent) => {
const handle = (e.target as HTMLElement | null)?.closest('[data-drag-handle="true"]');
if (!handle) {
e.preventDefault();
return;
}
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', elementName); e.dataTransfer.setData('text/plain', elementName);
draggedElementRef.current = elementName;
setDraggedElement(elementName); setDraggedElement(elementName);
setDragOverElement(null);
setDragOverPlacement(null);
}, []); }, []);
const handleDragOver = useCallback((e: React.DragEvent, elementName: string) => { const handleDragOver = useCallback((e: React.DragEvent, elementName: string) => {
e.preventDefault(); e.preventDefault();
e.dataTransfer.dropEffect = 'move'; e.dataTransfer.dropEffect = 'move';
if (draggedElement !== elementName) { const activeDragged = draggedElementRef.current;
if (activeDragged && activeDragged !== elementName) {
const placement = getDropPlacement(e.clientY, (e.currentTarget as HTMLElement).getBoundingClientRect());
setDragOverElement(elementName); setDragOverElement(elementName);
setDragOverPlacement(placement);
} }
}, [draggedElement]); }, [getDropPlacement]);
const handleDragLeave = useCallback((e: React.DragEvent) => { const handleDragLeave = useCallback((e: React.DragEvent) => {
// Only clear if we're leaving to a non-child element // Only clear if we're leaving to a non-child element
const relatedTarget = e.relatedTarget as HTMLElement; const relatedTarget = e.relatedTarget as HTMLElement;
if (!relatedTarget || !(e.currentTarget as HTMLElement).contains(relatedTarget)) { if (!relatedTarget || !(e.currentTarget as HTMLElement).contains(relatedTarget)) {
setDragOverElement(null); setDragOverElement(null);
setDragOverPlacement(null);
} }
}, []); }, []);
const handleDragEnd = useCallback(() => { const handleDragEnd = useCallback(() => {
setDraggedElement(null); resetDragState();
setDragOverElement(null); }, [resetDragState]);
}, []);
const handleDrop = useCallback((e: React.DragEvent, targetElementName: string) => { const handleDrop = useCallback((e: React.DragEvent, targetElementName: string) => {
e.preventDefault(); e.preventDefault();
const activeDragged = draggedElementRef.current;
if (!draggedElement || draggedElement === targetElementName) { if (!activeDragged || activeDragged === targetElementName) {
setDraggedElement(null); resetDragState();
setDragOverElement(null);
return; return;
} }
const newOrder = [...elementOrder]; const placement = dragOverPlacement || getDropPlacement(e.clientY, (e.currentTarget as HTMLElement).getBoundingClientRect());
const draggedIndex = newOrder.indexOf(draggedElement); const newOrder = reorderElements(elementOrder, activeDragged, targetElementName, placement);
const targetIndex = newOrder.indexOf(targetElementName);
if (draggedIndex === -1 || targetIndex === -1) { if (newOrder === elementOrder) {
setDraggedElement(null); resetDragState();
setDragOverElement(null);
return; return;
} }
// Remove dragged element and insert at target position pushHistorySnapshot();
newOrder.splice(draggedIndex, 1); commitElementOrderChange(newOrder);
newOrder.splice(targetIndex, 0, draggedElement); resetDragState();
}, [dragOverPlacement, elementOrder, getDropPlacement, reorderElements, pushHistorySnapshot, commitElementOrderChange, resetDragState]);
setElementOrder(newOrder);
setHasChanges(true);
setDraggedElement(null);
setDragOverElement(null);
// Apply visual reordering
if (isEditing) {
applyVisualReorder(newOrder);
window.dispatchEvent(new CustomEvent('myuibrix-reorder', {
detail: { order: newOrder, previewMode: true }
}));
}
}, [draggedElement, elementOrder, isEditing, applyVisualReorder]);
// Start with a blank layout: hide all elements and clear order // Start with a blank layout: hide all elements and clear order
const handleStartBlank = useCallback(() => { const handleStartBlank = useCallback(() => {
@@ -2661,6 +2772,8 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
const isDragging = draggedElement === elementName; const isDragging = draggedElement === elementName;
const isDragOver = dragOverElement === elementName; const isDragOver = dragOverElement === elementName;
const isDragOverBefore = isDragOver && dragOverPlacement === 'before';
const isDragOverAfter = isDragOver && dragOverPlacement === 'after';
return ( return (
<Box <Box
@@ -2668,16 +2781,24 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
p={3} p={3}
borderRadius="lg" borderRadius="lg"
border="2px" border="2px"
borderColor={isDragOver ? primaryColor : isSelected ? secondaryColor : 'gray.200'} borderColor={isSelected ? secondaryColor : isDragOver ? primaryColor : 'gray.200'}
bgGradient={isDragging ? 'linear(to-r, gray.100, gray.200)' : isSelected ? `linear(135deg, ${secondaryColor}15, ${secondaryColor}25)` : isVisible ? 'linear(to-r, white, gray.50)' : 'linear(to-r, gray.100, gray.150)'} bgGradient={isDragging ? 'linear(to-r, gray.100, gray.200)' : isSelected ? `linear(135deg, ${secondaryColor}15, ${secondaryColor}25)` : isVisible ? 'linear(to-r, white, gray.50)' : 'linear(to-r, gray.100, gray.150)'}
cursor={isDragging ? 'grabbing' : 'grab'} cursor={isDragging ? 'grabbing' : 'grab'}
opacity={isDragging ? 0.6 : isVisible ? 1 : 0.5} opacity={isDragging ? 0.6 : isVisible ? 1 : 0.5}
transition="all 0.3s cubic-bezier(0.4, 0, 0.2, 1)" transition="all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
transform={isDragOver ? 'scale(1.03) translateX(8px)' : undefined} transform={isDragOver ? 'scale(1.02) translateX(6px)' : undefined}
boxShadow={isSelected ? '0 4px 12px rgba(0,0,0,0.1)' : '0 2px 4px rgba(0,0,0,0.05)'} boxShadow={
isDragOverBefore
? `inset 0 4px 0 ${primaryColor}, 0 6px 16px rgba(0,0,0,0.12)`
: isDragOverAfter
? `inset 0 -4px 0 ${primaryColor}, 0 6px 16px rgba(0,0,0,0.12)`
: isSelected
? '0 4px 12px rgba(0,0,0,0.1)'
: '0 2px 4px rgba(0,0,0,0.05)'
}
_hover={{ _hover={{
borderColor: secondaryColor, borderColor: secondaryColor,
transform: isDragOver ? 'scale(1.03) translateX(8px)' : 'translateX(6px) translateY(-2px)', transform: isDragOver ? 'scale(1.02) translateX(6px)' : 'translateX(6px) translateY(-2px)',
boxShadow: '0 6px 16px rgba(0,0,0,0.12)' boxShadow: '0 6px 16px rgba(0,0,0,0.12)'
}} }}
draggable draggable
@@ -2708,13 +2829,21 @@ const MyUIbrixStyleEditor: React.FC<MyUIbrixStyleEditorProps> = ({ pageType, onC
> >
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<HStack flex={1} spacing={2}> <HStack flex={1} spacing={2}>
<Box
data-drag-handle="true"
p={1.5}
borderRadius="md"
bg={isDragOver ? `${primaryColor}18` : 'gray.100'}
cursor={isDragging ? 'grabbing' : 'grab'}
_hover={{ bg: `${primaryColor}15` }}
>
<Icon <Icon
as={FaGripVertical} as={FaGripVertical}
boxSize={4} boxSize={4}
color="gray.400" color="gray.500"
cursor="grab" pointerEvents="none"
_active={{ cursor: 'grabbing' }}
/> />
</Box>
<Box <Box
p={2} p={2}
bg={isSelected ? secondaryColor : `${secondaryColor}20`} bg={isSelected ? secondaryColor : `${secondaryColor}20`}
@@ -0,0 +1,129 @@
import React from 'react';
type HomeCardsSkeletonProps = {
actionWidth?: number | string;
cardCount?: number;
cardHeight?: number | string;
columns?: string;
layout?: 'grid' | 'carousel' | 'list';
minCardWidth?: number | string;
titleWidth?: number | string;
};
const SkeletonBar: React.FC<{ height?: number | string; width?: number | string }> = ({
height = 14,
width = '100%',
}) => (
<div
className="skeleton"
style={{
width,
height,
borderRadius: 999,
}}
/>
);
const SectionHeadSkeleton: React.FC<{
actionWidth?: number | string;
titleWidth?: number | string;
}> = ({
actionWidth = 104,
titleWidth = 180,
}) => (
<div className="section-head" style={{ marginTop: 0 }}>
<SkeletonBar height={24} width={titleWidth} />
<SkeletonBar height={14} width={actionWidth} />
</div>
);
export const HomeHeroSkeleton: React.FC = () => (
<div className="hero-grid" aria-hidden="true">
<div className="hero-card big skeleton" style={{ borderRadius: 16 }} />
<div className="small-col">
<div className="hero-card small skeleton" style={{ borderRadius: 16 }} />
<div className="hero-card small skeleton" style={{ borderRadius: 16 }} />
</div>
</div>
);
export const HomeCardsSkeleton: React.FC<HomeCardsSkeletonProps> = ({
actionWidth,
cardCount = 3,
cardHeight = 220,
columns = 'repeat(3, minmax(0, 1fr))',
layout = 'grid',
minCardWidth = 260,
titleWidth,
}) => {
const containerStyle: React.CSSProperties =
layout === 'carousel'
? {
display: 'flex',
gap: 18,
overflow: 'hidden',
padding: '8px 2px 16px 2px',
}
: layout === 'list'
? {
display: 'grid',
gridTemplateColumns: '1fr',
gap: 12,
}
: {
display: 'grid',
gridTemplateColumns: columns,
gap: 12,
};
return (
<div aria-hidden="true">
<SectionHeadSkeleton actionWidth={actionWidth} titleWidth={titleWidth} />
<div style={containerStyle}>
{Array.from({ length: cardCount }).map((_, index) => (
<div
key={index}
className="card skeleton"
style={{
borderRadius: 16,
flex: layout === 'carousel' ? '0 0 auto' : undefined,
height: cardHeight,
minWidth: layout === 'carousel' ? minCardWidth : undefined,
}}
/>
))}
</div>
</div>
);
};
export const HomeStandingsSkeleton: React.FC = () => (
<div aria-hidden="true">
<SectionHeadSkeleton actionWidth={92} titleWidth={140} />
<div className="table-card">
<div className="standings">
{Array.from({ length: 8 }).map((_, index) => (
<div
key={index}
className="standing-row skeleton"
style={{ borderRadius: 12 }}
/>
))}
</div>
</div>
</div>
);
export const HomeSponsorsSkeleton: React.FC = () => (
<div aria-hidden="true">
<div className="sponsors-grid">
{Array.from({ length: 8 }).map((_, index) => (
<div
key={index}
className="sponsor-tile skeleton"
style={{ minHeight: 90, borderRadius: 12 }}
/>
))}
</div>
</div>
);
+4 -2
View File
@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { FiChevronLeft, FiChevronRight } from 'react-icons/fi'; import { FiChevronLeft, FiChevronRight } from 'react-icons/fi';
import { TeamLogo } from '../common/TeamLogo'; import { TeamLogo } from '../common/TeamLogo';
import MatchCountdownText from '../common/MatchCountdownText';
import { sanitizeClubName } from '../../utils/url'; import { sanitizeClubName } from '../../utils/url';
export type NextMatchData = { export type NextMatchData = {
@@ -17,11 +18,12 @@ const NextMatch: React.FC<{
data: NextMatchData | null; data: NextMatchData | null;
competitionName?: string; competitionName?: string;
countdown?: string; countdown?: string;
kickoffIso?: string | null;
onPrev?: () => void; onPrev?: () => void;
onNext?: () => void; onNext?: () => void;
onOpen?: () => void; onOpen?: () => void;
elementProps?: any; elementProps?: any;
}> = ({ data, competitionName, countdown, onPrev, onNext, onOpen, elementProps }) => { }> = ({ data, competitionName, countdown, kickoffIso = null, onPrev, onNext, onOpen, elementProps }) => {
const show = data; const show = data;
return ( return (
<section <section
@@ -63,7 +65,7 @@ const NextMatch: React.FC<{
{competitionName && ( {competitionName && (
<div style={{ fontSize: '0.8rem', opacity: 0.85, marginBottom: 4 }}>{competitionName}</div> <div style={{ fontSize: '0.8rem', opacity: 0.85, marginBottom: 4 }}>{competitionName}</div>
)} )}
{countdown || '—'} {countdown ? countdown : <MatchCountdownText targetDate={kickoffIso} />}
<div style={{ fontSize: '0.8rem', opacity: 0.85 }}>Začátek zápasu</div> <div style={{ fontSize: '0.8rem', opacity: 0.85 }}>Začátek zápasu</div>
</div> </div>
+150 -60
View File
@@ -20,6 +20,23 @@ export interface NavbarData {
hasGallery: boolean; hasGallery: boolean;
} }
type CachedNavigationData = Pick<NavbarData, 'categories' | 'dynamicNavItems'>;
type CachedAvailabilityData = Pick<
NavbarData,
'hasTables' | 'hasActivities' | 'hasPlayers' | 'hasArticles' | 'hasVideos' | 'hasGallery'
>;
type CacheEntry<T> = {
expiresAt: number;
value: T;
};
const NAVBAR_CACHE_TTL_MS = 5 * 60 * 1000;
let cachedNavigationData: CacheEntry<CachedNavigationData> | null = null;
let navigationRequest: Promise<CachedNavigationData> | null = null;
let cachedAvailabilityData: CacheEntry<CachedAvailabilityData> | null = null;
let availabilityRequest: Promise<CachedAvailabilityData> | null = null;
export const useNavbarData = (isAdmin: boolean, settings?: any): NavbarData => { export const useNavbarData = (isAdmin: boolean, settings?: any): NavbarData => {
const [categories, setCategories] = useState<Category[] | null>(null); const [categories, setCategories] = useState<Category[] | null>(null);
const [dynamicNavItems, setDynamicNavItems] = useState<NavigationItem[]>([]); const [dynamicNavItems, setDynamicNavItems] = useState<NavigationItem[]>([]);
@@ -30,63 +47,90 @@ export const useNavbarData = (isAdmin: boolean, settings?: any): NavbarData => {
const [hasArticles, setHasArticles] = useState<boolean>(false); const [hasArticles, setHasArticles] = useState<boolean>(false);
const [hasVideos, setHasVideos] = useState<boolean>(false); const [hasVideos, setHasVideos] = useState<boolean>(false);
const [hasGallery, setHasGallery] = useState<boolean>(false); const [hasGallery, setHasGallery] = useState<boolean>(false);
const settingsCategories = Array.isArray(settings?.categories) ? (settings.categories as Category[]) : null;
const settingsHasVideos = Boolean(
settings?.youtube_url ||
settings?.videos_items?.length ||
settings?.videos?.length
);
const settingsHasGallery = Boolean(settings?.gallery_url || settings?.zonerama_url);
// Combined data loading effect
useEffect(() => { useEffect(() => {
let active = true; let active = true;
const loadAllData = async () => { const applyNavigationData = (data: CachedNavigationData) => {
try { setDynamicNavItems(data.dynamicNavItems);
// Load navigation and categories in parallel setCategories(
const [navItems, cats] = await Promise.all([ Array.isArray(data.categories) && data.categories.length > 0
getNavigationItems().catch(() => []), ? data.categories
getCategories().catch(() => []) : settingsCategories
]); );
setNavLoading(false);
};
if (active) { const loadNavigationData = async () => {
// Process navigation if (cachedNavigationData && cachedNavigationData.expiresAt > Date.now()) {
return cachedNavigationData.value;
}
if (!navigationRequest) {
navigationRequest = Promise.all([
getNavigationItems().catch(() => []),
getCategories().catch(() => []),
])
.then(([navItems, cats]) => {
const publicItems = Array.isArray(navItems) const publicItems = Array.isArray(navItems)
? navItems.filter(item => !item.requires_admin) ? navItems.filter((item) => !item.requires_admin)
: []; : [];
// Auto-seed if navigation is empty (only if user is authenticated as admin)
if (publicItems.length === 0 && isAdmin) { if (publicItems.length === 0 && isAdmin) {
try { try {
console.log('Navigation empty, auto-seeding...'); console.log('Navigation empty, auto-seeding...');
// Note: seedDefaultNavigation() would need to be imported
// For now, continue with empty navigation
} catch (seedError) { } catch (seedError) {
console.error('Auto-seed failed:', seedError); console.error('Auto-seed failed:', seedError);
} }
} }
setDynamicNavItems(publicItems); const value: CachedNavigationData = {
dynamicNavItems: publicItems,
categories: Array.isArray(cats) && cats.length > 0 ? cats : null,
};
// Process categories cachedNavigationData = {
if (Array.isArray(cats) && cats.length > 0) { expiresAt: Date.now() + NAVBAR_CACHE_TTL_MS,
setCategories(cats); value,
} else if (Array.isArray(settings?.categories)) { };
setCategories(settings.categories as any);
} else { return value;
setCategories(null); })
.finally(() => {
navigationRequest = null;
});
} }
return navigationRequest;
};
const run = async () => {
try {
const data = await loadNavigationData();
if (active) {
applyNavigationData(data);
} }
} catch (error) { } catch (error) {
console.error('Failed to load navigation/categories:', error); console.error('Failed to load navigation/categories:', error);
if (active) { if (active) {
setDynamicNavItems([]); setDynamicNavItems([]);
setCategories(Array.isArray(settings?.categories) ? settings.categories as any : null); setCategories(settingsCategories);
setNavLoading(false);
} }
} finally {
if (active) setNavLoading(false);
} }
}; };
loadAllData(); run();
return () => { active = false }; return () => { active = false };
}, [isAdmin, settings?.categories]); }, [isAdmin, settingsCategories]);
// Load content availability data in parallel
useEffect(() => { useEffect(() => {
let disposed = false; let disposed = false;
@@ -101,47 +145,93 @@ export const useNavbarData = (isAdmin: boolean, settings?: any): NavbarData => {
} catch { return path; } } catch { return path; }
}; };
const loadContentData = async () => { const applyAvailabilityData = (data: CachedAvailabilityData) => {
try { setHasTables(data.hasTables);
// Load all content availability checks in parallel setHasActivities(data.hasActivities);
const [ setHasPlayers(data.hasPlayers);
tablesResponse, setHasArticles(data.hasArticles);
events, setHasVideos(data.hasVideos || settingsHasVideos);
players, setHasGallery(data.hasGallery || settingsHasGallery);
articlesResponse, };
youtube,
manifest const loadAvailabilityData = async () => {
] = await Promise.allSettled([ if (cachedAvailabilityData && cachedAvailabilityData.expiresAt > Date.now()) {
return cachedAvailabilityData.value;
}
if (!availabilityRequest) {
availabilityRequest = Promise.allSettled([
fetch(resolveBackendUrl('/cache/prefetch/facr_tables.json'), { cache: 'no-cache' }), fetch(resolveBackendUrl('/cache/prefetch/facr_tables.json'), { cache: 'no-cache' }),
getEvents().catch(() => []), getEvents().catch(() => []),
getPlayers().catch(() => []), getPlayers().catch(() => []),
getArticles({ page: 1, page_size: 1, published: true }).catch(() => ({ total: 0 })), getArticles({ page: 1, page_size: 1, published: true }).catch(() => ({ total: 0 })),
getCachedYouTube().catch(() => null), getCachedYouTube().catch(() => null),
getZoneramaManifestWithFallbacks().catch(() => []) getZoneramaManifestWithFallbacks().catch(() => []),
]); ])
.then(async ([tablesResponse, events, players, articlesResponse, youtube, manifest]) => {
let hasTables = false;
if (!disposed) {
// Process tables
if (tablesResponse.status === 'fulfilled') { if (tablesResponse.status === 'fulfilled') {
const res = tablesResponse.value; const res = tablesResponse.value;
if (res.ok) { if (res.ok) {
const json = await res.json(); const json = await res.json();
const anyRows = Array.isArray(json?.competitions) && hasTables =
json.competitions.some((c: any) => Array.isArray(c?.table?.overall) && c.table.overall.length > 0); Array.isArray(json?.competitions) &&
setHasTables(!!anyRows); json.competitions.some(
} else { (competition: any) =>
setHasTables(false); Array.isArray(competition?.table?.overall) &&
competition.table.overall.length > 0
);
} }
} else {
setHasTables(false);
} }
// Process other content with proper type guards const value: CachedAvailabilityData = {
setHasActivities(events.status === 'fulfilled' && Array.isArray(events.value) && events.value.length > 0); hasTables,
setHasPlayers(players.status === 'fulfilled' && Array.isArray(players.value) && players.value.length > 0); hasActivities:
setHasArticles(articlesResponse.status === 'fulfilled' && typeof articlesResponse.value === 'object' && articlesResponse.value !== null && 'total' in articlesResponse.value && (articlesResponse.value as any).total > 0); events.status === 'fulfilled' && Array.isArray(events.value) && events.value.length > 0,
setHasVideos(youtube.status === 'fulfilled' && youtube.value !== null && typeof youtube.value === 'object' && 'videos' in youtube.value && Array.isArray((youtube.value as any).videos) && (youtube.value as any).videos.length > 0); hasPlayers:
setHasGallery(manifest.status === 'fulfilled' && Array.isArray(manifest.value) && manifest.value.length > 0); players.status === 'fulfilled' &&
Array.isArray(players.value) &&
players.value.length > 0,
hasArticles:
articlesResponse.status === 'fulfilled' &&
typeof articlesResponse.value === 'object' &&
articlesResponse.value !== null &&
'total' in articlesResponse.value &&
(articlesResponse.value as any).total > 0,
hasVideos:
youtube.status === 'fulfilled' &&
youtube.value !== null &&
typeof youtube.value === 'object' &&
'videos' in youtube.value &&
Array.isArray((youtube.value as any).videos) &&
(youtube.value as any).videos.length > 0,
hasGallery:
manifest.status === 'fulfilled' &&
Array.isArray(manifest.value) &&
manifest.value.length > 0,
};
cachedAvailabilityData = {
expiresAt: Date.now() + NAVBAR_CACHE_TTL_MS,
value,
};
return value;
})
.finally(() => {
availabilityRequest = null;
});
}
return availabilityRequest;
};
const run = async () => {
try {
const data = await loadAvailabilityData();
if (!disposed) {
applyAvailabilityData(data);
} }
} catch (error) { } catch (error) {
console.error('Failed to load content data:', error); console.error('Failed to load content data:', error);
@@ -150,15 +240,15 @@ export const useNavbarData = (isAdmin: boolean, settings?: any): NavbarData => {
setHasActivities(false); setHasActivities(false);
setHasPlayers(false); setHasPlayers(false);
setHasArticles(false); setHasArticles(false);
setHasVideos(false); setHasVideos(settingsHasVideos);
setHasGallery(false); setHasGallery(settingsHasGallery);
} }
} }
}; };
loadContentData(); run();
return () => { disposed = true; }; return () => { disposed = true; };
}, []); }, [settingsHasGallery, settingsHasVideos]);
return { return {
categories, categories,
+33 -18
View File
@@ -1,5 +1,21 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { PageElementConfig, getPageElementConfigs } from '../services/pageElements'; import { getPageElementConfigs } from '../services/pageElementsPublic';
const detectEditMode = () => {
try {
if (typeof document !== 'undefined' && document.body?.classList?.contains('myuibrix-edit-mode')) {
return true;
}
if (typeof window !== 'undefined') {
const params = new URLSearchParams(window.location.search);
return params.get('myuibrix') === 'edit';
}
} catch {
return false;
}
return false;
};
export const usePageElementConfig = (pageType: string, elementName: string, defaultVariant: string = 'unified') => { export const usePageElementConfig = (pageType: string, elementName: string, defaultVariant: string = 'unified') => {
const [variant, setVariant] = useState<string>(defaultVariant); const [variant, setVariant] = useState<string>(defaultVariant);
@@ -10,7 +26,7 @@ export const usePageElementConfig = (pageType: string, elementName: string, defa
const loadConfig = async () => { const loadConfig = async () => {
try { try {
const configs = await getPageElementConfigs(pageType); const configs = await getPageElementConfigs(pageType, { force: detectEditMode() });
if (active) { if (active) {
const config = configs.find(c => c.element_name === elementName); const config = configs.find(c => c.element_name === elementName);
if (config) { if (config) {
@@ -46,6 +62,7 @@ export const useAllPageElementConfigs = (pageType: string) => {
useEffect(() => { useEffect(() => {
let active = true; let active = true;
const isEditingMode = detectEditMode();
// Helper function to apply DOM order // Helper function to apply DOM order
const applyDOMOrder = (order: string[]) => { const applyDOMOrder = (order: string[]) => {
@@ -257,10 +274,9 @@ body [data-element="${name}"],
styleEl.textContent = `/* MyUIbrix Dynamic Styles - Auto-generated */\n${cssBlocks.join('\n\n')}`; styleEl.textContent = `/* MyUIbrix Dynamic Styles - Auto-generated */\n${cssBlocks.join('\n\n')}`;
// Force browser to recalculate styles // Immediate reflow is only useful in live preview mode and is expensive in production.
if (typeof document !== 'undefined') { if (isEditingMode && typeof document !== 'undefined') {
// Trigger a reflow to ensure styles are applied immediately document.body.offsetHeight;
document.body.offsetHeight; // Read operation forces reflow
} }
} catch (e) { } catch (e) {
console.error('[MyUIbrix] Style injection failed:', e); console.error('[MyUIbrix] Style injection failed:', e);
@@ -269,7 +285,7 @@ body [data-element="${name}"],
const loadConfigs = async () => { const loadConfigs = async () => {
try { try {
const data = await getPageElementConfigs(pageType); const data = await getPageElementConfigs(pageType, { force: isEditingMode });
if (active) { if (active) {
const configMap: Record<string, string> = {}; const configMap: Record<string, string> = {};
const visMap: Record<string, boolean> = {}; const visMap: Record<string, boolean> = {};
@@ -336,17 +352,6 @@ body [data-element="${name}"],
// Inject style properties so they apply even without inline spreading // Inject style properties so they apply even without inline spreading
updateInjectedStyleProps(stylesMap); updateInjectedStyleProps(stylesMap);
// Apply initial order to DOM only in editor/preview mode
const isEditingMode = (() => {
try {
if (typeof document !== 'undefined' && (document.body?.classList?.contains('myuibrix-edit-mode'))) return true;
const params = new URLSearchParams(window.location.search);
return params.get('myuibrix') === 'edit';
} catch {
return false;
}
})();
if (order.length > 0 && isEditingMode) { if (order.length > 0 && isEditingMode) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
applyDOMOrder(order); applyDOMOrder(order);
@@ -364,6 +369,16 @@ body [data-element="${name}"],
loadConfigs(); loadConfigs();
if (!isEditingMode) {
return () => {
active = false;
try {
const s = document.getElementById('myuibrix-style-props');
if (s) s.remove();
} catch {}
};
}
// Listen for live updates from MyUIbrix editor (ONLY in preview mode) // Listen for live updates from MyUIbrix editor (ONLY in preview mode)
const handleMyUIbrixChange = ((event: CustomEvent) => { const handleMyUIbrixChange = ((event: CustomEvent) => {
const { elementName, variant, visible, previewMode, timestamp } = event.detail; const { elementName, variant, visible, previewMode, timestamp } = event.detail;
+42 -13
View File
@@ -10,6 +10,9 @@ interface UmamiConfig {
script_url: string; script_url: string;
} }
let cachedUmamiConfig: UmamiConfig | null | undefined;
let umamiConfigPromise: Promise<UmamiConfig | null> | null = null;
// Extend window object to include umami // Extend window object to include umami
declare global { declare global {
interface Window { interface Window {
@@ -31,31 +34,57 @@ export const useUmami = () => {
pathname === '/setup'; pathname === '/setup';
}; };
const fetchConfigOnce = async () => {
if (cachedUmamiConfig !== undefined) {
return cachedUmamiConfig;
}
if (!umamiConfigPromise) {
umamiConfigPromise = axios
.get(`${API_URL}/insights/config`)
.then((response) => {
cachedUmamiConfig = response.data as UmamiConfig;
return cachedUmamiConfig;
})
.catch((error) => {
console.error('Failed to load Umami config:', error);
cachedUmamiConfig = null;
return null;
})
.finally(() => {
umamiConfigPromise = null;
});
}
return umamiConfigPromise;
};
useEffect(() => { useEffect(() => {
// Don't load Umami for admin pages
if (isAdminRoute(location.pathname)) { if (isAdminRoute(location.pathname)) {
console.log('Umami tracking disabled for admin pages');
return; return;
} }
// Fetch Umami configuration from backend let active = true;
const fetchConfig = async () => {
try { const ensureConfig = async () => {
const response = await axios.get(`${API_URL}/insights/config`); const umamiConfig = await fetchConfigOnce();
const umamiConfig = response.data as UmamiConfig; if (!active || !umamiConfig) {
return;
}
setConfig(umamiConfig); setConfig(umamiConfig);
// If enabled and not already loaded, inject the script
if (umamiConfig.enabled && umamiConfig.website_id && !isLoaded) { if (umamiConfig.enabled && umamiConfig.website_id && !isLoaded) {
loadUmamiScript(umamiConfig.script_url, umamiConfig.website_id); loadUmamiScript(umamiConfig.script_url, umamiConfig.website_id);
} }
} catch (error) {
console.error('Failed to load Umami config:', error);
}
}; };
fetchConfig(); ensureConfig();
}, [location.pathname]);
return () => {
active = false;
};
}, [isLoaded, location.pathname]);
// Track page views when location changes (skip admin routes for Umami) // Track page views when location changes (skip admin routes for Umami)
useEffect(() => { useEffect(() => {
+1 -1
View File
@@ -14,7 +14,7 @@ import './styles/custom-editor.css';
import './styles/public-rich-content.css'; import './styles/public-rich-content.css';
// Import i18n configuration // Import i18n configuration
import './i18n'; import './i18n';
import { theme } from './App'; import { theme } from './theme/siteTheme';
import AppLazy from './App.lazy'; import AppLazy from './App.lazy';
import { ColorModeScript } from '@chakra-ui/react'; import { ColorModeScript } from '@chakra-ui/react';
import { HelmetProvider } from 'react-helmet-async'; import { HelmetProvider } from 'react-helmet-async';
+4 -2
View File
@@ -4,11 +4,13 @@ import { Box, Container, Heading, Text, Stack, Image, SimpleGrid, Divider } from
import { usePublicSettings } from '../hooks/usePublicSettings'; import { usePublicSettings } from '../hooks/usePublicSettings';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { assetUrl } from '../utils/url'; import { assetUrl } from '../utils/url';
import { sanitizeRichHtml } from '../utils/sanitizeHtml';
import NewsletterCTA from '../components/common/NewsletterCTA'; import NewsletterCTA from '../components/common/NewsletterCTA';
const ClubPage: React.FC = () => { const ClubPage: React.FC = () => {
const { data: settings } = usePublicSettings(); const { data: settings } = usePublicSettings();
const { t } = useTranslation(); const { t } = useTranslation();
const aboutHtml = React.useMemo(() => sanitizeRichHtml(settings?.about_html), [settings?.about_html]);
return ( return (
<MainLayout> <MainLayout>
@@ -24,9 +26,9 @@ const ClubPage: React.FC = () => {
</Box> </Box>
</Stack> </Stack>
{settings?.about_html ? ( {aboutHtml ? (
<Box> <Box>
<Box className="prose" color="gray.800" dangerouslySetInnerHTML={{ __html: settings.about_html as any }} /> <Box className="prose" color="gray.800" dangerouslySetInnerHTML={{ __html: aboutHtml }} />
</Box> </Box>
) : ( ) : (
<Box> <Box>
+29 -65
View File
@@ -31,7 +31,14 @@ import MatchModal from '../components/home/MatchModal';
import { useAllPageElementConfigs } from '../hooks/usePageElementConfig'; import { useAllPageElementConfigs } from '../hooks/usePageElementConfig';
import { API_URL } from '../services/api'; import { API_URL } from '../services/api';
import { TeamLogo } from '../components/common/TeamLogo'; import { TeamLogo } from '../components/common/TeamLogo';
import MatchCountdownText, { buildKickoffIso } from '../components/common/MatchCountdownText';
import ClubHeroTopbar from '../components/home/ClubHeroTopbar'; import ClubHeroTopbar from '../components/home/ClubHeroTopbar';
import {
HomeCardsSkeleton,
HomeHeroSkeleton,
HomeSponsorsSkeleton,
HomeStandingsSkeleton,
} from '../components/home/HomeLoadingSkeletons';
import NewsList from '../components/pack/NewsList'; import NewsList from '../components/pack/NewsList';
const StandingsCard = React.lazy(() => import('../components/pack/StandingsCard')); const StandingsCard = React.lazy(() => import('../components/pack/StandingsCard'));
import NextMatch from '../components/pack/NextMatch'; import NextMatch from '../components/pack/NextMatch';
@@ -75,7 +82,6 @@ const HomePage: React.FC = () => {
// Local state now starts empty; filled by FACR/cache/live APIs // Local state now starts empty; filled by FACR/cache/live APIs
const [news, setNews] = useState<NewsItem[]>([]); const [news, setNews] = useState<NewsItem[]>([]);
const [matches, setMatches] = useState<MatchItem[]>([]); const [matches, setMatches] = useState<MatchItem[]>([]);
const [countdown, setCountdown] = useState<string>('');
const [clubName, setClubName] = useState<string>(''); const [clubName, setClubName] = useState<string>('');
const [clubLogo, setClubLogo] = useState<string>(''); const [clubLogo, setClubLogo] = useState<string>('');
const [standings, setStandings] = useState<any[]>([]); const [standings, setStandings] = useState<any[]>([]);
@@ -771,49 +777,6 @@ const HomePage: React.FC = () => {
// MyUIbrix events are handled by useAllPageElementConfigs hook // MyUIbrix events are handled by useAllPageElementConfigs hook
// It automatically updates getVariant() and isVisible() when changes occur in edit mode // It automatically updates getVariant() and isVisible() when changes occur in edit mode
// Countdown to next match (uses selected competition upcoming if available)
useEffect(() => {
const getUpcomingForComp = (c: any) => {
const items = Array.isArray(c?.matches) ? c.matches : [];
const future = items
.map((m: any) => ({ m, t: new Date(`${m.date}T${(m.time || '00:00')}:00`).getTime() }))
.filter((x: any) => !isNaN(x.t) && x.t > Date.now())
.sort((a: any, b: any) => a.t - b.t);
return future[0]?.m || null;
};
const getNextKickoff = () => {
if (facrCompetitions.length) {
const sel = facrCompetitions[Math.max(0, Math.min(matchesTab, facrCompetitions.length - 1))];
const up = getUpcomingForComp(sel);
if (up) {
const iso = `${up.date}T${(up.time || '00:00')}:00`;
const d = new Date(iso);
return isNaN(d.getTime()) ? null : d;
}
}
if (!matches.length) return null;
const m = matches[0];
const iso = `${m.date}T${(m.time || '00:00')}:00`;
const d = new Date(iso);
return isNaN(d.getTime()) ? null : d;
};
const update = () => {
const next = getNextKickoff();
if (!next) { setCountdown(''); return; }
const diff = next.getTime() - Date.now();
if (diff <= 0) { setCountdown('Začátek'); return; }
const s = Math.floor(diff / 1000);
const days = Math.floor(s / 86400);
const hrs = Math.floor((s % 86400) / 3600);
const mins = Math.floor((s % 3600) / 60);
const secs = s % 60;
setCountdown(`${days} d ${hrs} h ${mins} m ${secs} s`);
};
update();
const id = setInterval(update, 1000);
return () => clearInterval(id);
}, [matches, facrCompetitions, matchesTab]);
useEffect(() => { useEffect(() => {
let active = true; let active = true;
(async () => { (async () => {
@@ -1181,7 +1144,14 @@ const HomePage: React.FC = () => {
<div>{show?.home || clubName}</div> <div>{show?.home || clubName}</div>
</div> </div>
<div className="meta"> <div className="meta">
{isFuture ? <><div style={{ fontWeight: 800 }}>{countdown || '—'}</div><div>Začátek</div></> : <div style={{ fontWeight: 800 }}>{show?.score || '—'}</div>} {isFuture ? (
<>
<div style={{ fontWeight: 800 }}>
<MatchCountdownText targetDate={buildKickoffIso(show?.date, show?.time)} />
</div>
<div>Začátek</div>
</>
) : <div style={{ fontWeight: 800 }}>{show?.score || '—'}</div>}
</div> </div>
<div className="team"> <div className="team">
<img src={assetUrl(show?.away_logo_url) || '/images/club-opponent.svg'} alt="Hosté" /> <img src={assetUrl(show?.away_logo_url) || '/images/club-opponent.svg'} alt="Hosté" />
@@ -1682,7 +1652,7 @@ const HomePage: React.FC = () => {
{getVariant('hero', heroStyle) === 'scroller' && isVisible('hero', true) && ( {getVariant('hero', heroStyle) === 'scroller' && isVisible('hero', true) && (
<section key={`hero-scroller-${refreshKey}`} data-element="hero" data-variant={getVariant('hero', heroStyle)} style={{ position: 'relative', ...getStyles('hero') }}> <section key={`hero-scroller-${refreshKey}`} data-element="hero" data-variant={getVariant('hero', heroStyle)} style={{ position: 'relative', ...getStyles('hero') }}>
<Suspense fallback={<div style={{ minHeight: 240 }} />}> <Suspense fallback={<HomeHeroSkeleton />}>
<BlogCardsScroller /> <BlogCardsScroller />
</Suspense> </Suspense>
</section> </section>
@@ -1694,7 +1664,7 @@ const HomePage: React.FC = () => {
data-variant={getVariant('hero', heroStyle)} data-variant={getVariant('hero', heroStyle)}
style={{ position: 'relative', ...getStyles('hero') }} style={{ position: 'relative', ...getStyles('hero') }}
> >
<Suspense fallback={<div style={{ minHeight: 280 }} />}> <Suspense fallback={<HomeHeroSkeleton />}>
<BlogSwiper fallbackArticles={heroFallbackArticles} /> <BlogSwiper fallbackArticles={heroFallbackArticles} />
</Suspense> </Suspense>
</section> </section>
@@ -1736,7 +1706,7 @@ const HomePage: React.FC = () => {
<NextMatch <NextMatch
data={show} data={show}
competitionName={comp?.name} competitionName={comp?.name}
countdown={countdown} kickoffIso={buildKickoffIso(show?.date, show?.time)}
onPrev={() => { setNextCompIdx(prevIdx); setMatchesTab(prevIdx); }} onPrev={() => { setNextCompIdx(prevIdx); setMatchesTab(prevIdx); }}
onNext={() => { setNextCompIdx(nextIdx); setMatchesTab(nextIdx); }} onNext={() => { setNextCompIdx(nextIdx); setMatchesTab(nextIdx); }}
onOpen={handleNextMatchClick} onOpen={handleNextMatchClick}
@@ -1769,7 +1739,7 @@ const HomePage: React.FC = () => {
away: next?.awayTeam || 'Soupeř', away: next?.awayTeam || 'Soupeř',
away_logo_url: next?.awayLogoURL, away_logo_url: next?.awayLogoURL,
}} }}
countdown={countdown} kickoffIso={buildKickoffIso(next?.date, next?.time)}
elementProps={{ 'data-element': 'matches', 'data-variant': getVariant('matches', 'compact'), 'aria-live': 'polite', style: { position: 'relative', ...getStyles('matches') } }} elementProps={{ 'data-element': 'matches', 'data-variant': getVariant('matches', 'compact'), 'aria-live': 'polite', style: { position: 'relative', ...getStyles('matches') } }}
/> />
</div> </div>
@@ -1786,7 +1756,7 @@ const HomePage: React.FC = () => {
{/* Matches slider with scores by competition (moved after news+tables) */} {/* Matches slider with scores by competition (moved after news+tables) */}
{facrCompetitions.length > 0 && ( {facrCompetitions.length > 0 && (
defer ? ( defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton layout="carousel" cardCount={3} cardHeight={160} minCardWidth={340} titleWidth={140} actionWidth={96} />}>
<MatchesSlider <MatchesSlider
key={`matches-slider-${refreshKey}-${getVariant('matches-slider', 'carousel')}`} key={`matches-slider-${refreshKey}-${getVariant('matches-slider', 'carousel')}`}
comps={facrCompetitions as any} comps={facrCompetitions as any}
@@ -1800,7 +1770,7 @@ const HomePage: React.FC = () => {
elementProps={{ 'data-element': 'matches-slider', 'data-variant': getVariant('matches-slider', 'carousel'), style: { position: 'relative', ...getStyles('matches-slider') } }} elementProps={{ 'data-element': 'matches-slider', 'data-variant': getVariant('matches-slider', 'carousel'), style: { position: 'relative', ...getStyles('matches-slider') } }}
/> />
</Suspense> </Suspense>
) : null ) : <HomeCardsSkeleton layout="carousel" cardCount={3} cardHeight={160} minCardWidth={340} titleWidth={140} actionWidth={96} />
)} )}
{facrCompetitions.length === 0 && isLoading && ( {facrCompetitions.length === 0 && isLoading && (
@@ -1871,7 +1841,7 @@ const HomePage: React.FC = () => {
<a href="/tabulky" className="see-all" style={{ fontSize: '0.85rem' }}>{t('nav.view_all')} <FiArrowRight size={14} /></a> <a href="/tabulky" className="see-all" style={{ fontSize: '0.85rem' }}>{t('nav.view_all')} <FiArrowRight size={14} /></a>
</div> </div>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeStandingsSkeleton />}>
<StandingsCard <StandingsCard
variant={((): 'logos'|'plain' => { const v = getVariant('table_rows', 'logos'); return v === 'plain' ? 'plain' : 'logos'; })()} variant={((): 'logos'|'plain' => { const v = getVariant('table_rows', 'logos'); return v === 'plain' ? 'plain' : 'logos'; })()}
rows={(matchingStanding?.table || matchingStanding?.rows || []) as any} rows={(matchingStanding?.table || matchingStanding?.rows || []) as any}
@@ -2040,10 +2010,10 @@ const HomePage: React.FC = () => {
<section key={`gallery-${refreshKey}-${getVariant('gallery', 'grid')}`} data-element="gallery" data-variant={getVariant('gallery', 'grid')} aria-labelledby="home-gallery-heading" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '700px', ...getStyles('gallery') }}> <section key={`gallery-${refreshKey}-${getVariant('gallery', 'grid')}`} data-element="gallery" data-variant={getVariant('gallery', 'grid')} aria-labelledby="home-gallery-heading" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '700px', ...getStyles('gallery') }}>
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}> <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton cardCount={3} cardHeight={300} titleWidth={140} actionWidth={96} />}>
<GallerySection zoneramaUrl={galleryUrl} /> <GallerySection zoneramaUrl={galleryUrl} />
</Suspense> </Suspense>
) : null} ) : <HomeCardsSkeleton cardCount={3} cardHeight={300} titleWidth={140} actionWidth={96} />}
</div> </div>
</section> </section>
)} )}
@@ -2053,7 +2023,7 @@ const HomePage: React.FC = () => {
<section key={`videos-${refreshKey}-${getVariant('videos', 'carousel')}`} data-element="videos" data-variant={getVariant('videos', 'carousel')} aria-labelledby="home-videos-heading" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '700px', ...getStyles('videos') }}> <section key={`videos-${refreshKey}-${getVariant('videos', 'carousel')}`} data-element="videos" data-variant={getVariant('videos', 'carousel')} aria-labelledby="home-videos-heading" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '700px', ...getStyles('videos') }}>
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}> <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton layout="list" cardCount={3} cardHeight={240} titleWidth={110} actionWidth={110} />}>
<VideosSection <VideosSection
key={`videos-comp-${refreshKey}-${getVariant('videos', 'carousel')}`} key={`videos-comp-${refreshKey}-${getVariant('videos', 'carousel')}`}
variant={(getVariant('videos', 'carousel') as any) as 'grid' | 'carousel'} variant={(getVariant('videos', 'carousel') as any) as 'grid' | 'carousel'}
@@ -2080,7 +2050,7 @@ const HomePage: React.FC = () => {
<section key={`merch-${refreshKey}-${getVariant('merch', 'grid')}`} data-element="merch" data-variant={getVariant('merch', 'grid')} aria-labelledby="home-merch-heading" style={{ marginTop: 24, marginBottom: 24, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '600px', ...getStyles('merch') }}> <section key={`merch-${refreshKey}-${getVariant('merch', 'grid')}`} data-element="merch" data-variant={getVariant('merch', 'grid')} aria-labelledby="home-merch-heading" style={{ marginTop: 24, marginBottom: 24, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '600px', ...getStyles('merch') }}>
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}> <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton cardCount={5} cardHeight={180} titleWidth={170} actionWidth={96} />}>
<MerchSection variant={(getVariant('merch', 'grid') as any) as 'grid' | 'carousel' | 'featured' | 'list'} /> <MerchSection variant={(getVariant('merch', 'grid') as any) as 'grid' | 'carousel' | 'featured' | 'list'} />
</Suspense> </Suspense>
) : ( ) : (
@@ -2105,7 +2075,7 @@ const HomePage: React.FC = () => {
<section key={`poll-${refreshKey}-${getVariant('poll', 'vertical')}`} data-element="poll" data-variant={getVariant('poll', 'vertical')} aria-label="Anketa" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '500px', ...getStyles('poll') }}> <section key={`poll-${refreshKey}-${getVariant('poll', 'vertical')}`} data-element="poll" data-variant={getVariant('poll', 'vertical')} aria-label="Anketa" style={{ marginTop: 32, marginBottom: 32, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '500px', ...getStyles('poll') }}>
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}> <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 12px' }}>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton layout="grid" columns="1fr" cardCount={1} cardHeight={320} titleWidth={140} actionWidth={88} />}>
<PollsWidget featuredOnly={false} maxPolls={1} title="Anketa" /> <PollsWidget featuredOnly={false} maxPolls={1} title="Anketa" />
</Suspense> </Suspense>
) : ( ) : (
@@ -2132,7 +2102,7 @@ const HomePage: React.FC = () => {
<section key={`newsletter-${refreshKey}-${getVariant('newsletter', 'default')}`} data-element="newsletter" data-variant={getVariant('newsletter', 'default')} className="newsletter-cta" aria-label="Přihlášení k newsletteru" style={{ marginTop: 24, marginBottom: 24, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '420px', ...getStyles('newsletter') }}> <section key={`newsletter-${refreshKey}-${getVariant('newsletter', 'default')}`} data-element="newsletter" data-variant={getVariant('newsletter', 'default')} className="newsletter-cta" aria-label="Přihlášení k newsletteru" style={{ marginTop: 24, marginBottom: 24, position: 'relative', contentVisibility: 'auto' as any, containIntrinsicSize: '420px', ...getStyles('newsletter') }}>
<div className="card" style={{ maxWidth: 960, margin: '0 auto' }}> <div className="card" style={{ maxWidth: 960, margin: '0 auto' }}>
{defer ? ( {defer ? (
<Suspense fallback={null}> <Suspense fallback={<HomeCardsSkeleton layout="grid" columns="1fr" cardCount={1} cardHeight={280} titleWidth={180} actionWidth={120} />}>
<NewsletterSubscribe /> <NewsletterSubscribe />
</Suspense> </Suspense>
) : ( ) : (
@@ -2220,13 +2190,7 @@ const HomePage: React.FC = () => {
<div className="section-head"> <div className="section-head">
<h3 id="home-sponsors-heading">{t('nav.sponsors')}</h3> <h3 id="home-sponsors-heading">{t('nav.sponsors')}</h3>
</div> </div>
{isLoading && ordered.length === 0 && ( {isLoading && ordered.length === 0 && <HomeSponsorsSkeleton />}
<div className="sponsors-grid">
{[1,2,3,4,5,6,7,8].map(i => (
<div key={i} className="sponsor-tile skeleton" style={{ minHeight: 90, borderRadius: 12 }} />
))}
</div>
)}
{variant === 'grid' && ( {variant === 'grid' && (
<> <>
{general.length > 0 && ( {general.length > 0 && (
+1 -1
View File
@@ -1 +1 @@
/// <reference types="react-scripts" /> /// <reference types="vite/client" />
+13 -20
View File
@@ -1,5 +1,9 @@
import api from './api'; import api from './api';
import { IconType } from 'react-icons'; import { IconType } from 'react-icons';
import { invalidatePageElementConfigs } from './pageElementsPublic';
import type { PageElementConfig } from './pageElementsPublic';
export type { PageElementConfig } from './pageElementsPublic';
export { getPageElementConfigs } from './pageElementsPublic';
import { import {
FaRegClipboard, FaRegClipboard,
FaBullseye, FaBullseye,
@@ -37,26 +41,6 @@ import {
// Use shared API base URL // Use shared API base URL
export interface PageElementConfig {
id?: number;
page_type: string;
element_name: string;
variant: string;
visible?: boolean;
display_order?: number;
settings?: Record<string, any>;
created_at?: string;
updated_at?: string;
}
// Public endpoints
export const getPageElementConfigs = async (pageType: string): Promise<PageElementConfig[]> => {
const response = await api.get('/page-elements', {
params: { page_type: pageType }
});
return response.data || [];
};
// Admin endpoints // Admin endpoints
export const getAllPageElementConfigs = async (): Promise<PageElementConfig[]> => { export const getAllPageElementConfigs = async (): Promise<PageElementConfig[]> => {
const response = await api.get('/admin/page-elements'); const response = await api.get('/admin/page-elements');
@@ -65,20 +49,29 @@ export const getAllPageElementConfigs = async (): Promise<PageElementConfig[]> =
export const createOrUpdatePageElementConfig = async (config: Partial<PageElementConfig>): Promise<PageElementConfig> => { export const createOrUpdatePageElementConfig = async (config: Partial<PageElementConfig>): Promise<PageElementConfig> => {
const response = await api.post('/admin/page-elements', config); const response = await api.post('/admin/page-elements', config);
invalidatePageElementConfigs(config.page_type);
return response.data; return response.data;
}; };
export const updatePageElementConfig = async (id: number, config: Partial<PageElementConfig>): Promise<PageElementConfig> => { export const updatePageElementConfig = async (id: number, config: Partial<PageElementConfig>): Promise<PageElementConfig> => {
const response = await api.put(`/admin/page-elements/${id}`, config); const response = await api.put(`/admin/page-elements/${id}`, config);
invalidatePageElementConfigs(config.page_type);
return response.data; return response.data;
}; };
export const deletePageElementConfig = async (id: number): Promise<void> => { export const deletePageElementConfig = async (id: number): Promise<void> => {
await api.delete(`/admin/page-elements/${id}`); await api.delete(`/admin/page-elements/${id}`);
invalidatePageElementConfigs();
}; };
export const batchUpdatePageElementConfigs = async (configs: PageElementConfig[]): Promise<{ message: string; updated: number; created: number }> => { export const batchUpdatePageElementConfigs = async (configs: PageElementConfig[]): Promise<{ message: string; updated: number; created: number }> => {
const response = await api.post('/admin/page-elements/batch', configs); const response = await api.post('/admin/page-elements/batch', configs);
const pageTypes = new Set(configs.map((config) => config.page_type).filter(Boolean));
if (pageTypes.size === 0) {
invalidatePageElementConfigs();
} else {
pageTypes.forEach((pageType) => invalidatePageElementConfigs(pageType));
}
return response.data; return response.data;
}; };
@@ -0,0 +1,75 @@
import api from './api';
export interface PageElementConfig {
id?: number;
page_type: string;
element_name: string;
variant: string;
visible?: boolean;
display_order?: number;
settings?: Record<string, any>;
created_at?: string;
updated_at?: string;
}
type CacheEntry = {
expiresAt: number;
value: PageElementConfig[];
};
const PAGE_ELEMENT_CACHE_TTL_MS = 5 * 60 * 1000;
const pageElementCache = new Map<string, CacheEntry>();
const inFlightPageElementRequests = new Map<string, Promise<PageElementConfig[]>>();
export const invalidatePageElementConfigs = (pageType?: string) => {
if (pageType) {
pageElementCache.delete(pageType);
inFlightPageElementRequests.delete(pageType);
return;
}
pageElementCache.clear();
inFlightPageElementRequests.clear();
};
export const getPageElementConfigs = async (
pageType: string,
options?: { force?: boolean }
): Promise<PageElementConfig[]> => {
const force = options?.force === true;
const cacheKey = String(pageType || '').trim();
if (!force) {
const cached = pageElementCache.get(cacheKey);
if (cached && cached.expiresAt > Date.now()) {
return cached.value;
}
const pending = inFlightPageElementRequests.get(cacheKey);
if (pending) {
return pending;
}
}
const request = api
.get('/page-elements', {
params: { page_type: pageType },
})
.then((response) => {
const data = Array.isArray(response.data) ? response.data : [];
pageElementCache.set(cacheKey, {
expiresAt: Date.now() + PAGE_ELEMENT_CACHE_TTL_MS,
value: data,
});
return data;
})
.finally(() => {
inFlightPageElementRequests.delete(cacheKey);
});
if (!force) {
inFlightPageElementRequests.set(cacheKey, request);
}
return request;
};
-152
View File
@@ -1,152 +0,0 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
function resolveBackendOrigin() {
const raw = process.env.REACT_APP_API_BASE_URL || process.env.REACT_APP_API_URL || '';
const fallback = 'http://127.0.0.1:8080';
try {
if (!raw || raw.startsWith('/')) {
return fallback;
}
const u = new URL(raw);
u.pathname = '/';
return u.toString();
} catch (e) {
return fallback;
}
}
module.exports = function(app) {
// Proxy /uploads requests to backend
app.use(
'/uploads',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /uploads:', err);
},
})
);
app.use(
'/api',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /api:', err);
},
})
);
// Proxy short links and tracked redirect so CRA dev server doesn't 404 or capture the route
app.use(
'/s',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /s:', err);
},
})
);
app.use(
'/r',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /r:', err);
},
})
);
// Proxy /static requests to backend (for any static assets served by Go)
app.use(
'/static',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /static:', err);
},
})
);
// Proxy /dist requests to backend (assets served by Go under /dist)
app.use(
'/dist',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /dist:', err);
},
})
);
// Proxy /cache requests to backend (for FACR cache files, etc.)
app.use(
'/cache',
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for /cache:', err);
},
})
);
// Additional common static/image paths that may be referenced directly
app.use(
[
'/images',
'/img',
'/media',
'/files',
'/logos',
'/avatars',
'/downloads',
'/public',
'/favicon.ico',
],
createProxyMiddleware({
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for image/static path:', err);
},
})
);
// Fallback: proxy any direct image file requests to the backend
// This will not affect Webpack Dev Server assets since they are handled earlier in the middleware chain
app.use(
createProxyMiddleware(
(pathname, req) => {
try {
if (pathname.startsWith('/sockjs-node') || pathname.startsWith('/ws')) return false;
return /\.(?:png|jpe?g|gif|svg|webp|ico|avif)$/i.test(pathname);
} catch {
return false;
}
},
{
target: resolveBackendOrigin(),
changeOrigin: true,
logLevel: 'debug',
onError: (err, req, res) => {
console.error('Proxy error for image extension fallback:', err);
},
}
)
);
};
+150
View File
@@ -0,0 +1,150 @@
import { extendTheme } from '@chakra-ui/react';
export const theme = extendTheme({
config: {
initialColorMode: 'light',
useSystemColorMode: false,
},
colors: {
brand: {
50: '#e6f7ff',
100: '#b3e0ff',
200: '#80caff',
300: '#4db3ff',
400: '#1a9cff',
500: 'var(--club-primary, #0b5cff)',
600: '#0066cc',
700: '#004d99',
800: '#003366',
900: '#001a33',
},
},
semanticTokens: {
colors: {
'brand.primary': {
default: 'var(--club-primary, #0b5cff)',
},
'brand.secondary': {
default: 'var(--club-secondary, #ffd200)',
},
'brand.accent': {
default: 'var(--club-accent, #141414)',
},
'text.onPrimary': {
default: 'var(--club-text-on-primary, #ffffff)',
},
'bg.app': {
default: '#f8f9fb',
_dark: '#0f1115',
},
'text.app': {
default: '#1a1a1a',
_dark: '#e8eaf0',
},
'border.subtle': {
default: 'rgba(0,0,0,0.06)',
_dark: 'rgba(255,255,255,0.12)',
},
'bg.card': {
default: '#ffffff',
_dark: '#1a1d29',
},
'bg.elevated': {
default: '#ffffff',
_dark: '#242831',
},
},
},
styles: {
global: {
'html, body, #root': {
height: '100%',
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
body: {
bg: 'bg.app',
color: 'text.app',
lineHeight: 1.5,
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
'h1, h2, h3, h4, h5, h6': {
fontFamily: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
a: {
transition: 'color 0.2s ease',
},
'::selection': {
background: 'brand.accent',
color: 'black',
},
},
},
components: {
Container: {
baseStyle: {
px: { base: 4, md: 6 },
},
sizes: {
'7xl': '88rem',
},
},
Button: {
baseStyle: {
fontWeight: '700',
borderRadius: 'md',
letterSpacing: '0.4px',
_hover: { transform: 'translateY(-1px)', boxShadow: 'md' },
_active: { transform: 'translateY(0)' },
},
variants: {
solid: {
bg: 'brand.primary',
color: 'text.onPrimary',
_hover: { filter: 'brightness(0.95)' },
},
outline: {
border: '2px solid',
borderColor: 'brand.primary',
color: 'brand.primary',
_hover: { bg: 'rgba(0,0,0,0.02)' },
},
ghost: {
color: 'brand.secondary',
_hover: { bg: 'rgba(0,0,0,0.04)' },
},
},
},
Card: {
baseStyle: {
container: {
borderRadius: 'lg',
boxShadow: 'sm',
overflow: 'hidden',
transition: 'all 0.2s',
borderWidth: '1px',
borderColor: 'border.subtle',
_hover: { transform: 'translateY(-4px)', boxShadow: 'lg' },
},
},
},
Divider: {
baseStyle: {
borderColor: 'border.subtle',
},
},
Heading: {
baseStyle: {
fontFamily: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
},
Text: {
baseStyle: {
fontFamily: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
},
},
fonts: {
heading: 'var(--font-heading, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
body: 'var(--font-body, Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial)',
},
});
+39
View File
@@ -0,0 +1,39 @@
import DOMPurify from 'dompurify';
const ADDITIONAL_TAGS = ['iframe'];
const ADDITIONAL_ATTRS = [
'allow',
'allowfullscreen',
'class',
'data-bullets',
'data-filters',
'data-img-id',
'data-list',
'rel',
'style',
'target',
];
export function sanitizeRichHtml(html: string | null | undefined): string {
const sanitized = DOMPurify.sanitize(html ?? '', {
USE_PROFILES: { html: true },
ADD_TAGS: ADDITIONAL_TAGS,
ADD_ATTR: ADDITIONAL_ATTRS,
});
if (typeof window === 'undefined' || !sanitized) {
return sanitized;
}
const template = window.document.createElement('template');
template.innerHTML = sanitized;
template.content.querySelectorAll<HTMLAnchorElement>('a[target="_blank"]').forEach((anchor) => {
const rel = new Set((anchor.getAttribute('rel') ?? '').split(/\s+/).filter(Boolean));
rel.add('noopener');
rel.add('noreferrer');
anchor.setAttribute('rel', Array.from(rel).join(' '));
});
return template.innerHTML;
}
+5 -1
View File
@@ -22,7 +22,11 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"types": [
"vite/client",
"vitest/globals"
]
}, },
"include": [ "include": [
"src" "src"
+102
View File
@@ -0,0 +1,102 @@
import path from 'node:path';
import { URL } from 'node:url';
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
function resolveBackendOrigin(env: Record<string, string>) {
const raw = env.REACT_APP_API_BASE_URL || env.REACT_APP_API_URL || '';
const fallback = 'http://127.0.0.1:8080';
try {
if (!raw || raw.startsWith('/')) {
return fallback;
}
const parsed = new URL(raw);
parsed.pathname = '/';
parsed.search = '';
parsed.hash = '';
return parsed.toString();
} catch {
return fallback;
}
}
function buildProcessEnv(mode: string, env: Record<string, string>, base: string) {
const processEnv: Record<string, string> = {
NODE_ENV: mode === 'production' ? 'production' : mode,
PUBLIC_URL: base === '/' ? '' : base.replace(/\/$/, ''),
};
for (const [key, value] of Object.entries(env)) {
if (key.startsWith('REACT_APP_')) {
processEnv[key] = value;
}
}
return processEnv;
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const base = env.PUBLIC_URL ? (env.PUBLIC_URL.endsWith('/') ? env.PUBLIC_URL : `${env.PUBLIC_URL}/`) : '/';
const backendOrigin = resolveBackendOrigin(env);
const processEnv = buildProcessEnv(mode, env, base);
const commonProxy = {
target: backendOrigin,
changeOrigin: true,
secure: false,
};
return {
base,
publicDir: 'public',
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
define: {
'process.env': JSON.stringify(processEnv),
global: 'globalThis',
},
build: {
outDir: 'build',
assetsDir: 'static',
emptyOutDir: true,
sourcemap: false,
},
server: {
host: '0.0.0.0',
port: 3000,
proxy: {
'/api': commonProxy,
'/uploads': commonProxy,
'/s': commonProxy,
'/r': commonProxy,
'/static': commonProxy,
'/dist': commonProxy,
'/cache': commonProxy,
'/images': commonProxy,
'/img': commonProxy,
'/media': commonProxy,
'/files': commonProxy,
'/logos': commonProxy,
'/avatars': commonProxy,
'/downloads': commonProxy,
'/public': commonProxy,
'/favicon.ico': commonProxy,
},
},
preview: {
host: '0.0.0.0',
port: 4173,
},
test: {
environment: 'jsdom',
globals: true,
setupFiles: 'src/setupTests.ts',
},
};
});
+52 -18
View File
@@ -1,8 +1,6 @@
module fotbal-club module fotbal-club
go 1.23.0 go 1.25.0
toolchain go1.24.4
require ( require (
github.com/PuerkitoBio/goquery v1.10.3 github.com/PuerkitoBio/goquery v1.10.3
@@ -16,14 +14,17 @@ require (
github.com/jung-kurt/gofpdf v1.16.2 github.com/jung-kurt/gofpdf v1.16.2
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762
github.com/muesli/kmeans v0.3.1 github.com/muesli/kmeans v0.3.1
github.com/pressly/goose/v3 v3.27.0
github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_golang v1.20.5
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.10.0 github.com/sqlc-dev/sqlc v1.30.0
github.com/stretchr/testify v1.11.1
github.com/vanng822/go-premailer v1.25.0 github.com/vanng822/go-premailer v1.25.0
github.com/xuri/excelize/v2 v2.9.0 github.com/xuri/excelize/v2 v2.9.0
golang.org/x/crypto v0.39.0 go.uber.org/zap v1.27.1
golang.org/x/crypto v0.48.0
golang.org/x/image v0.18.0 golang.org/x/image v0.18.0
golang.org/x/text v0.26.0 golang.org/x/text v0.34.0
gopkg.in/mail.v2 v2.3.1 gopkg.in/mail.v2 v2.3.1
gorm.io/datatypes v1.2.6 gorm.io/datatypes v1.2.6
gorm.io/driver/postgres v1.5.7 gorm.io/driver/postgres v1.5.7
@@ -32,58 +33,91 @@ require (
) )
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect cel.dev/expr v0.25.1 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cubicdaiya/gonp v1.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/structtag v1.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-sql-driver/mysql v1.9.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/google/cel-go v0.26.1 // indirect
github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect github.com/jackc/pgx/v5 v5.8.0 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pganalyze/pg_query_go/v6 v6.1.0 // indirect
github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb // indirect
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
github.com/pingcap/log v1.1.0 // indirect
github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.19.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/riza-io/grpc-go v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
github.com/vanng822/css v1.0.1 // indirect github.com/vanng822/css v1.0.1 // indirect
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 // indirect
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/net v0.41.0 // indirect golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
golang.org/x/sync v0.15.0 // indirect golang.org/x/net v0.50.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sync v0.19.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect golang.org/x/sys v0.41.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect
google.golang.org/grpc v1.79.1 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.6 // indirect gorm.io/driver/mysql v1.5.6 // indirect
modernc.org/libc v1.68.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.46.1 // indirect
) )
+191 -32
View File
@@ -1,9 +1,15 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -17,12 +23,18 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/cubicdaiya/gonp v1.0.4 h1:ky2uIAJh81WiLcGKBVD5R7KsM/36W6IqqTy6Bo6rGws=
github.com/cubicdaiya/gonp v1.0.4/go.mod h1:iWGuP/7+JVTn02OWhRemVbMmG1DOUnmrGTYYACpOI0I=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE= github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
@@ -31,6 +43,10 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -40,8 +56,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
@@ -51,21 +67,34 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ=
github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@@ -78,14 +107,17 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -96,8 +128,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
github.com/microsoft/go-mssqldb v1.9.6 h1:1MNQg5UiSsokiPz3++K2KPx4moKrwIqly1wv+RyCKTw=
github.com/microsoft/go-mssqldb v1.9.6/go.mod h1:yYMPDufyoF2vVuVCUGtZARr06DKFIhMrluTcgWlXpr4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -112,44 +146,81 @@ github.com/muesli/kmeans v0.3.1 h1:KshLQ8wAETfLWOJKMuDCVYHnafddSa1kwGh/IypGIzY=
github.com/muesli/kmeans v0.3.1/go.mod h1:8/OvJW7cHc1BpRf8URb43m+vR105DDe+Kj1WcFXYDqc= github.com/muesli/kmeans v0.3.1/go.mod h1:8/OvJW7cHc1BpRf8URb43m+vR105DDe+Kj1WcFXYDqc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls=
github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50=
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb h1:3pSi4EDG6hg0orE1ndHkXvX6Qdq2cZn8gAPir8ymKZk=
github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg=
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 h1:tdMsjOqUR7YXHoBitzdebTvOjs/swniBTOLy5XiMtuE=
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86/go.mod h1:exzhVYca3WRtd6gclGNErRWb1qEgff3LYta0LvRmON4=
github.com/pingcap/log v1.1.0 h1:ELiPxACz7vdo1qAvvaWJg1NrYFoY6gqAh/+Uo6aXdD8=
github.com/pingcap/log v1.1.0/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0 h1:W3rpAI3bubR6VWOcwxDIG0Gz9G5rl5b3SL116T0vBt0=
github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0/go.mod h1:+8feuexTKcXHZF/dkDfvCwEyBAmgb4paFc3/WeYV2eE=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pressly/goose/v3 v3.27.0 h1:/D30gVTuQhu0WsNZYbJi4DMOsx1lNq+6SkLe+Wp59BM=
github.com/pressly/goose/v3 v3.27.0/go.mod h1:3ZBeCXqzkgIRvrEMDkYh1guvtoJTU5oMMuDdkutoM78=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00= github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/riza-io/grpc-go v0.2.0 h1:2HxQKFVE7VuYstcJ8zqpN84VnAoJ4dCL6YFhJewNcHQ=
github.com/riza-io/grpc-go v0.2.0/go.mod h1:2bDvR9KkKC3KhtlSHfR3dAXjUMT86kg4UfWFyVGWqi8=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/sqlc-dev/sqlc v1.30.0 h1:H4HrNwPc0hntxGWzAbhlfplPRN4bQpXFx+CaEMcKz6c=
github.com/sqlc-dev/sqlc v1.30.0/go.mod h1:QnEN+npugyhUg1A+1kkYM3jc2OMOFsNlZ1eh8mdhad0=
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
@@ -158,6 +229,10 @@ github.com/vanng822/css v1.0.1 h1:10yiXc4e8NI8ldU6mSrWmSWMuyWgPr9DZ63RSlsgDw8=
github.com/vanng822/css v1.0.1/go.mod h1:tcnB1voG49QhCrwq1W0w5hhGasvOg+VQp9i9H1rCM1w= github.com/vanng822/css v1.0.1/go.mod h1:tcnB1voG49QhCrwq1W0w5hhGasvOg+VQp9i9H1rCM1w=
github.com/vanng822/go-premailer v1.25.0 h1:hGHKfroCXrCDTyGVR8o4HCON5/HWvc7C1uocS+VnaZs= github.com/vanng822/go-premailer v1.25.0 h1:hGHKfroCXrCDTyGVR8o4HCON5/HWvc7C1uocS+VnaZs=
github.com/vanng822/go-premailer v1.25.0/go.mod h1:8WJKIPZtegxqSOA8+eDFx7QNesKmMYfGEIodLTJqrtM= github.com/vanng822/go-premailer v1.25.0/go.mod h1:8WJKIPZtegxqSOA8+eDFx7QNesKmMYfGEIodLTJqrtM=
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 h1:mJdDDPblDfPe7z7go8Dvv1AJQDI3eQ/5xith3q2mFlo=
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07/go.mod h1:Ak17IJ037caFp4jpCw/iQQ7/W74Sqpb1YuKJU6HTKfM=
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 h1:OvLBa8SqJnZ6P+mjlzc2K7PM22rRUPE1x32G9DTPrC4=
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52/go.mod h1:jMeV4Vpbi8osrE/pKUxRZkVaA0EX7NZN0A9/oRzgpgY=
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA= github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY= github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
@@ -166,6 +241,33 @@ github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmji
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A= github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
@@ -175,18 +277,24 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -196,8 +304,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -205,8 +313,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -219,8 +327,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -239,25 +347,48 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck= gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck=
@@ -274,5 +405,33 @@ gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.30.2 h1:4yPaaq9dXYXZ2V8s1UgrC3KIj580l2N4ClrLwnbv2so=
modernc.org/ccgo/v4 v4.30.2/go.mod h1:yZMnhWEdW0qw3EtCndG1+ldRrVGS+bIwyWmAWzS0XEw=
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.68.0 h1:PJ5ikFOV5pwpW+VqCK1hKJuEWsonkIJhhIXyuF/91pQ=
modernc.org/libc v1.68.0/go.mod h1:NnKCYeoYgsEqnY3PgvNgAeaJnso968ygU8Z0DxjoEc0=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+24 -10
View File
@@ -19,8 +19,6 @@ type SEOController struct {
} }
func NewSEOController(db *gorm.DB) *SEOController { func NewSEOController(db *gorm.DB) *SEOController {
// Ensure settings table has the SEO fields
_ = db.AutoMigrate(&models.Settings{})
return &SEOController{DB: db} return &SEOController{DB: db}
} }
@@ -313,14 +311,30 @@ func (s *SEOController) UpdateSEOSettings(c *gin.Context) {
// Update only provided fields // Update only provided fields
updates := map[string]interface{}{} updates := map[string]interface{}{}
if body.SiteTitle != nil { updates["site_title"] = strings.TrimSpace(*body.SiteTitle) } if body.SiteTitle != nil {
if body.SiteDescription != nil { updates["site_description"] = strings.TrimSpace(*body.SiteDescription) } updates["site_title"] = strings.TrimSpace(*body.SiteTitle)
if body.MetaKeywords != nil { updates["meta_keywords"] = strings.TrimSpace(*body.MetaKeywords) } }
if body.DefaultOGImageURL != nil { updates["default_og_image_url"] = strings.TrimSpace(*body.DefaultOGImageURL) } if body.SiteDescription != nil {
if body.TwitterHandle != nil { updates["twitter_handle"] = strings.TrimSpace(*body.TwitterHandle) } updates["site_description"] = strings.TrimSpace(*body.SiteDescription)
if body.CanonicalBaseURL != nil { updates["canonical_base_url"] = strings.TrimSpace(*body.CanonicalBaseURL) } }
if body.AdditionalMeta != nil { updates["additional_meta"] = *body.AdditionalMeta } if body.MetaKeywords != nil {
if body.EnableIndexing != nil { updates["enable_indexing"] = *body.EnableIndexing } updates["meta_keywords"] = strings.TrimSpace(*body.MetaKeywords)
}
if body.DefaultOGImageURL != nil {
updates["default_og_image_url"] = strings.TrimSpace(*body.DefaultOGImageURL)
}
if body.TwitterHandle != nil {
updates["twitter_handle"] = strings.TrimSpace(*body.TwitterHandle)
}
if body.CanonicalBaseURL != nil {
updates["canonical_base_url"] = strings.TrimSpace(*body.CanonicalBaseURL)
}
if body.AdditionalMeta != nil {
updates["additional_meta"] = *body.AdditionalMeta
}
if body.EnableIndexing != nil {
updates["enable_indexing"] = *body.EnableIndexing
}
if len(updates) > 0 { if len(updates) > 0 {
if err := s.DB.Model(&settings).Updates(updates).Error; err != nil { if err := s.DB.Model(&settings).Updates(updates).Error; err != nil {
+31
View File
@@ -0,0 +1,31 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package eshopreporting
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}
@@ -0,0 +1,159 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: eshop_reporting.sql
package eshopreporting
import (
"context"
"database/sql"
)
const listOrderStatusBreakdown = `-- name: ListOrderStatusBreakdown :many
SELECT
status,
COUNT(*)::bigint AS order_count
FROM eshop_orders
WHERE deleted_at IS NULL
GROUP BY status
ORDER BY order_count DESC, status ASC
`
type ListOrderStatusBreakdownRow struct {
Status sql.NullString `json:"status"`
OrderCount int64 `json:"order_count"`
}
func (q *Queries) ListOrderStatusBreakdown(ctx context.Context) ([]ListOrderStatusBreakdownRow, error) {
rows, err := q.db.QueryContext(ctx, listOrderStatusBreakdown)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListOrderStatusBreakdownRow
for rows.Next() {
var i ListOrderStatusBreakdownRow
if err := rows.Scan(&i.Status, &i.OrderCount); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listRecentOrderSummaries = `-- name: ListRecentOrderSummaries :many
SELECT
o.id,
o.order_number,
o.status,
o.total_amount_cents,
o.currency,
o.shipping_method,
o.shipping_price_cents,
o.created_at,
COALESCE(p.status, '') AS payment_status,
COALESCE(s.status, '') AS shipping_status
FROM eshop_orders AS o
LEFT JOIN LATERAL (
SELECT ep.status
FROM eshop_payments AS ep
WHERE ep.order_id = o.id
AND ep.deleted_at IS NULL
ORDER BY ep.created_at DESC
LIMIT 1
) AS p ON TRUE
LEFT JOIN LATERAL (
SELECT sl.status
FROM eshop_shipping_labels AS sl
WHERE sl.order_id = o.id
AND sl.deleted_at IS NULL
ORDER BY sl.created_at DESC
LIMIT 1
) AS s ON TRUE
WHERE o.deleted_at IS NULL
ORDER BY o.created_at DESC
LIMIT $1
`
type ListRecentOrderSummariesRow struct {
ID int32 `json:"id"`
OrderNumber string `json:"order_number"`
Status sql.NullString `json:"status"`
TotalAmountCents int64 `json:"total_amount_cents"`
Currency sql.NullString `json:"currency"`
ShippingMethod sql.NullString `json:"shipping_method"`
ShippingPriceCents sql.NullInt64 `json:"shipping_price_cents"`
CreatedAt sql.NullTime `json:"created_at"`
PaymentStatus string `json:"payment_status"`
ShippingStatus string `json:"shipping_status"`
}
func (q *Queries) ListRecentOrderSummaries(ctx context.Context, limit int32) ([]ListRecentOrderSummariesRow, error) {
rows, err := q.db.QueryContext(ctx, listRecentOrderSummaries, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListRecentOrderSummariesRow
for rows.Next() {
var i ListRecentOrderSummariesRow
if err := rows.Scan(
&i.ID,
&i.OrderNumber,
&i.Status,
&i.TotalAmountCents,
&i.Currency,
&i.ShippingMethod,
&i.ShippingPriceCents,
&i.CreatedAt,
&i.PaymentStatus,
&i.ShippingStatus,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const summarizeOrderRevenue = `-- name: SummarizeOrderRevenue :one
SELECT
COUNT(*)::bigint AS order_count,
COALESCE(SUM(total_amount_cents), 0)::bigint AS gross_revenue_cents,
COALESCE(SUM(shipping_price_cents), 0)::bigint AS shipping_revenue_cents
FROM eshop_orders
WHERE deleted_at IS NULL
AND created_at >= $1
AND created_at < $2
`
type SummarizeOrderRevenueParams struct {
CreatedAt sql.NullTime `json:"created_at"`
CreatedAt_2 sql.NullTime `json:"created_at_2"`
}
type SummarizeOrderRevenueRow struct {
OrderCount int64 `json:"order_count"`
GrossRevenueCents int64 `json:"gross_revenue_cents"`
ShippingRevenueCents int64 `json:"shipping_revenue_cents"`
}
func (q *Queries) SummarizeOrderRevenue(ctx context.Context, arg SummarizeOrderRevenueParams) (SummarizeOrderRevenueRow, error) {
row := q.db.QueryRowContext(ctx, summarizeOrderRevenue, arg.CreatedAt, arg.CreatedAt_2)
var i SummarizeOrderRevenueRow
err := row.Scan(&i.OrderCount, &i.GrossRevenueCents, &i.ShippingRevenueCents)
return i, err
}
+165
View File
@@ -0,0 +1,165 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package eshopreporting
import (
"database/sql"
)
type EshopCart struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
UserID sql.NullInt32 `json:"user_id"`
SessionToken sql.NullString `json:"session_token"`
Currency sql.NullString `json:"currency"`
Completed sql.NullBool `json:"completed"`
}
type EshopCartItem struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
CartID int32 `json:"cart_id"`
ProductID int32 `json:"product_id"`
VariantID sql.NullInt32 `json:"variant_id"`
Quantity int32 `json:"quantity"`
UnitPriceCents int64 `json:"unit_price_cents"`
Currency sql.NullString `json:"currency"`
}
type EshopOrder struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
OrderNumber string `json:"order_number"`
UserID sql.NullInt32 `json:"user_id"`
SessionToken sql.NullString `json:"session_token"`
Email sql.NullString `json:"email"`
FirstName sql.NullString `json:"first_name"`
LastName sql.NullString `json:"last_name"`
BillingAddressJson sql.NullString `json:"billing_address_json"`
ShippingAddressJson sql.NullString `json:"shipping_address_json"`
Status sql.NullString `json:"status"`
TotalAmountCents int64 `json:"total_amount_cents"`
Currency sql.NullString `json:"currency"`
ShippingMethod sql.NullString `json:"shipping_method"`
ShippingPriceCents sql.NullInt64 `json:"shipping_price_cents"`
ShippingDataJson sql.NullString `json:"shipping_data_json"`
MetadataJson sql.NullString `json:"metadata_json"`
}
type EshopOrderItem struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
OrderID int32 `json:"order_id"`
ProductID int32 `json:"product_id"`
VariantID sql.NullInt32 `json:"variant_id"`
Name string `json:"name"`
Sku sql.NullString `json:"sku"`
Quantity int32 `json:"quantity"`
UnitPriceCents int64 `json:"unit_price_cents"`
Currency sql.NullString `json:"currency"`
VatRate sql.NullString `json:"vat_rate"`
}
type EshopPayment struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
OrderID int32 `json:"order_id"`
Provider sql.NullString `json:"provider"`
ProviderPaymentID sql.NullString `json:"provider_payment_id"`
Status sql.NullString `json:"status"`
AmountCents int64 `json:"amount_cents"`
Currency sql.NullString `json:"currency"`
RawPayloadJson sql.NullString `json:"raw_payload_json"`
}
type EshopProduct struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
Slug string `json:"slug"`
Name string `json:"name"`
ShortDescription sql.NullString `json:"short_description"`
DescriptionHtml sql.NullString `json:"description_html"`
PriceCents int64 `json:"price_cents"`
Currency sql.NullString `json:"currency"`
VatRate sql.NullString `json:"vat_rate"`
Active sql.NullBool `json:"active"`
StockMode sql.NullString `json:"stock_mode"`
DefaultImageUrl sql.NullString `json:"default_image_url"`
GalleryJson sql.NullString `json:"gallery_json"`
Tags sql.NullString `json:"tags"`
MetadataJson sql.NullString `json:"metadata_json"`
CategoryID sql.NullInt32 `json:"category_id"`
}
type EshopProductCategory struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
Slug string `json:"slug"`
Name string `json:"name"`
ParentID sql.NullInt32 `json:"parent_id"`
DisplayOrder sql.NullInt32 `json:"display_order"`
Active sql.NullBool `json:"active"`
}
type EshopProductVariant struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
ProductID int32 `json:"product_id"`
Sku sql.NullString `json:"sku"`
Name sql.NullString `json:"name"`
AttributesJson sql.NullString `json:"attributes_json"`
StockQty sql.NullInt32 `json:"stock_qty"`
Barcode sql.NullString `json:"barcode"`
ImageUrl sql.NullString `json:"image_url"`
}
type EshopSetting struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
DefaultCurrency sql.NullString `json:"default_currency"`
SupportedCurrencies sql.NullString `json:"supported_currencies"`
DefaultCountry sql.NullString `json:"default_country"`
ShippingOptionsJson sql.NullString `json:"shipping_options_json"`
TermsUrl sql.NullString `json:"terms_url"`
ReturnsPolicyUrl sql.NullString `json:"returns_policy_url"`
SupportEmail sql.NullString `json:"support_email"`
SupportPhone sql.NullString `json:"support_phone"`
}
type EshopShippingLabel struct {
ID int32 `json:"id"`
CreatedAt sql.NullTime `json:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
OrderID int32 `json:"order_id"`
Carrier sql.NullString `json:"carrier"`
PacketaPacketID sql.NullString `json:"packeta_packet_id"`
TrackingNumber sql.NullString `json:"tracking_number"`
LabelUrl sql.NullString `json:"label_url"`
Status sql.NullString `json:"status"`
HistoryJson sql.NullString `json:"history_json"`
}
type User struct {
ID int32 `json:"id"`
}
@@ -0,0 +1,17 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package eshopreporting
import (
"context"
)
type Querier interface {
ListOrderStatusBreakdown(ctx context.Context) ([]ListOrderStatusBreakdownRow, error)
ListRecentOrderSummaries(ctx context.Context, limit int32) ([]ListRecentOrderSummariesRow, error)
SummarizeOrderRevenue(ctx context.Context, arg SummarizeOrderRevenueParams) (SummarizeOrderRevenueRow, error)
}
var _ Querier = (*Queries)(nil)
+121
View File
@@ -0,0 +1,121 @@
package dbschema
import (
"fotbal-club/internal/models"
"gorm.io/gorm"
)
// AllModels returns the complete set of persisted models used to bootstrap the schema.
func AllModels() []interface{} {
return []interface{}{
&models.SetupInfo{},
&models.ClubInfo{},
&models.Settings{},
&models.User{},
&models.UserProfile{},
&models.Article{},
&models.Category{},
&models.ArticleTeamLink{},
&models.ArticleMatchLink{},
&models.Team{},
&models.Player{},
&models.Club{},
&models.Sponsor{},
&models.Banner{},
&models.ScoreboardState{},
&models.ContactCategory{},
&models.Contact{},
&models.ContactMessage{},
&models.NewsletterSubscription{},
&models.PasswordReset{},
&models.VisitorEvent{},
&models.AboutPage{},
&models.EmailLog{},
&models.EmailEvent{},
&models.NewsletterSentLog{},
&models.MatchNotification{},
&models.BlogNotification{},
&models.MatchOverride{},
&models.TeamLogoOverride{},
&models.NavigationItem{},
&models.SocialLink{},
&models.PageElementConfig{},
&models.ShortLink{},
&models.LinkClick{},
&models.Poll{},
&models.PollOption{},
&models.PollVote{},
&models.Comment{},
&models.CommentReaction{},
&models.CommentBan{},
&models.UnbanRequest{},
&models.CommentReport{},
&models.PointsTransaction{},
&models.Achievement{},
&models.UserAchievement{},
&models.RewardItem{},
&models.RewardRedemption{},
&models.Sweepstake{},
&models.SweepstakePrize{},
&models.SweepstakeEntry{},
&models.SweepstakeWinner{},
&models.UploadedFile{},
&models.FileUsage{},
&models.ErrorEvent{},
&models.CompetitionAlias{},
&models.Clothing{},
&models.Language{},
&models.Translation{},
&models.ContentTranslation{},
&models.UserLanguagePreference{},
&models.ManualCompetition{},
&models.ManualMatch{},
&models.ManualTableRow{},
&models.Event{},
&models.EventAttachment{},
&models.QRCode{},
&models.EshopProductCategory{},
&models.EshopProduct{},
&models.EshopProductVariant{},
&models.EshopCart{},
&models.EshopCartItem{},
&models.EshopOrder{},
&models.EshopOrderItem{},
&models.EshopPayment{},
&models.EshopShippingLabel{},
&models.EshopSettings{},
&models.Facility{},
&models.FacilityAvailabilityRule{},
&models.FacilityBooking{},
&models.FacilityEquipment{},
&models.FacilityMaintenance{},
&models.WeatherCondition{},
&models.FacilityBookingTemplate{},
&models.Budget{},
&models.Sponsorship{},
&models.SponsorshipPayment{},
&models.SponsorshipDocument{},
&models.Expense{},
&models.ExpenseDocument{},
&models.FinancialReport{},
&models.FinancialSettings{},
&models.Invoice{},
&models.InvoiceItem{},
&models.InvoicePayment{},
&models.InvoiceCustomer{},
&models.InvoiceTemplate{},
&models.InvoiceSettings{},
&models.InvoiceSequence{},
&models.AuditLog{},
&models.TicketType{},
&models.TicketCampaign{},
&models.CampaignTicketType{},
&models.Ticket{},
&models.TicketAvailability{},
}
}
func AutoMigrate(db *gorm.DB) error {
return db.AutoMigrate(AllModels()...)
}
+2
View File
@@ -0,0 +1,2 @@
VITE_API_BASE_URL=
VITE_SITE_URL=https://example.com
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+46
View File
@@ -0,0 +1,46 @@
# MyClub Landing
Samostatná publikovatelná landing page pro `MyClub` v root složce `/landing`.
## Stack
- React + TypeScript + Vite
- Tailwind CSS v4
- shadcn/ui primitives
- Montserrat variable font
- Form submission přes existující `POST /api/v1/contact`
## Development
```bash
cd landing
npm install
npm run dev
```
Dev server běží na `http://localhost:4174`.
Výchozí proxy posílá `/api/*` na `http://localhost:8080`, takže při lokálním běhu backendu není potřeba nastavovat extra URL.
## Environment
Zkopírujte `.env.example` podle potřeby:
```bash
cp .env.example .env
```
Podporované proměnné:
- `VITE_API_BASE_URL`: volitelné. Pokud je prázdné, používá se same-origin `/api/...`
- `VITE_SITE_URL`: volitelné. Pokud je nastavené, doplní canonical a absolutní OG/Twitter URL
## Build
```bash
cd landing
npm run build
npm run preview
```
Výstup je v `landing/dist`.
+25
View File
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
+32
View File
@@ -0,0 +1,32 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
'react-refresh/only-export-components': ['error', { allowConstantExport: true }],
},
},
{
files: ['src/components/ui/button.tsx', 'src/components/ui/badge.tsx'],
rules: {
'react-refresh/only-export-components': 'off',
},
},
])
+34
View File
@@ -0,0 +1,34 @@
<!doctype html>
<html lang="cs">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="rgb(108 56 217)" />
<meta name="color-scheme" content="light" />
<meta
name="description"
content="MyClub spojuje klubový web, MyUIbrix builder, zápasy, obsah, partnery, newslettery i provozní workflow do jednoho přehledného systému pro sportovní kluby."
/>
<meta property="og:type" content="website" />
<meta property="og:site_name" content="MyClub" />
<meta property="og:title" content="MyClub | Web, obsah a provoz klubu v jednom systému" />
<meta
property="og:description"
content="MyClub spojuje klubový web, MyUIbrix builder, zápasy, obsah, partnery, newslettery i provozní workflow do jednoho přehledného systému pro sportovní kluby."
/>
<meta property="og:image" content="/og-cover.svg" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="MyClub | Web, obsah a provoz klubu v jednom systému" />
<meta
name="twitter:description"
content="MyClub spojuje klubový web, MyUIbrix builder, zápasy, obsah, partnery, newslettery i provozní workflow do jednoho přehledného systému pro sportovní kluby."
/>
<meta name="twitter:image" content="/og-cover.svg" />
<title>MyClub | Web, obsah a provoz klubu v jednom systému</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
+9068
View File
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
{
"name": "landing",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@fontsource-variable/montserrat": "^5.2.8",
"@hookform/resolvers": "^5.2.2",
"axios": "^1.13.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.577.0",
"radix-ui": "^1.4.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-hook-form": "^7.71.2",
"shadcn": "^4.0.6",
"tailwind-merge": "^3.5.0",
"tw-animate-css": "^1.4.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
"@tailwindcss/vite": "^4.2.1",
"@types/node": "^24.12.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.2.0",
"eslint": "^9.39.4",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.4.0",
"tailwindcss": "^4.2.1",
"tailwindcss-animate": "^1.0.7",
"typescript": "~5.9.3",
"typescript-eslint": "^8.56.1",
"vite": "^7.3.1"
}
}
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="MyClub">
<rect width="128" height="128" rx="32" fill="rgb(255 255 255)" />
<rect x="10" y="10" width="108" height="108" rx="28" fill="rgb(255 255 255)" stroke="rgba(17,24,39,0.14)" stroke-width="2" />
<path d="M32 94V34h12l20 30 20-30h12v60H84V58L64 87 44 58v36H32Z" fill="rgb(108 56 217)" />
<circle cx="98" cy="34" r="12" fill="rgba(255,153,51,0.24)" />
<circle cx="98" cy="34" r="6" fill="rgb(255 153 51)" />
</svg>

After

Width:  |  Height:  |  Size: 514 B

+18
View File
@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-label="MyClub Open Graph Cover">
<rect width="1200" height="630" fill="rgb(255 255 255)" />
<rect x="42" y="42" width="1116" height="546" rx="36" fill="rgb(255 255 255)" stroke="rgba(17,24,39,0.1)" stroke-width="2" />
<circle cx="180" cy="126" r="88" fill="rgba(108,56,217,0.14)" />
<circle cx="1032" cy="128" r="72" fill="rgba(255,153,51,0.18)" />
<path d="M110 454V182h68l112 168 112-168h68v272h-68V291L290 429 178 291v163h-68Z" fill="rgb(108 56 217)" />
<rect x="552" y="170" width="520" height="290" rx="30" fill="rgba(108,56,217,0.05)" stroke="rgba(17,24,39,0.08)" />
<rect x="590" y="210" width="230" height="132" rx="24" fill="rgb(255 255 255)" stroke="rgba(17,24,39,0.08)" />
<rect x="848" y="210" width="186" height="60" rx="20" fill="rgba(255,153,51,0.18)" />
<rect x="848" y="286" width="186" height="56" rx="20" fill="rgb(255 255 255)" stroke="rgba(17,24,39,0.08)" />
<rect x="590" y="362" width="444" height="58" rx="20" fill="rgb(255 255 255)" stroke="rgba(17,24,39,0.08)" />
<text x="552" y="520" fill="rgb(17 24 39)" font-family="Montserrat, sans-serif" font-size="58" font-weight="700" letter-spacing="-2">
MyClub
</text>
<text x="552" y="574" fill="rgb(75 85 99)" font-family="Montserrat, sans-serif" font-size="28">
Web, obsah a provoz klubu v jednom systému
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+429
View File
@@ -0,0 +1,429 @@
import {
ArrowRight,
Check,
ChevronRight,
LayoutDashboard,
MailPlus,
Sparkles,
Image as ImageIcon,
} from 'lucide-react'
import {
contactChecklist,
faqItems,
featureCards,
navItems,
operationalPillars,
proofPoints,
workflowSteps,
} from '@/content'
import { useLandingSeo } from '@/hooks/useLandingSeo'
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { ContactForm } from '@/components/landing/ContactForm'
import { HeroVisual } from '@/components/landing/HeroVisual'
import { SectionHeading } from '@/components/landing/SectionHeading'
import { SiteHeader } from '@/components/landing/SiteHeader'
import { VideoText } from '@/components/ui/video-text'
useLandingSeo()
export default function App() {
return (
<div id="top" className="landing-shell">
<SiteHeader items={navItems} />
<main className="pb-16 pt-24 sm:pt-28">
<section className="relative overflow-hidden pb-14 pt-8 sm:pb-18">
<div className="section-shell grid gap-12 lg:grid-cols-[1.02fr_0.98fr] lg:items-center">
<div className="relative z-10 flex flex-col gap-7">
<Badge className="eyebrow-pill max-w-max">
MyClub SaaS pro sportovní kluby
</Badge>
<div className="flex flex-col gap-5">
<div className="relative h-[120px] w-full overflow-hidden rounded-2xl">
<VideoText
src="https://cdn.magicui.design/ocean-small.webm"
className="absolute inset-0"
fontSize={18}
fontWeight="800"
>
Jeden systém pro web, obsah a provoz vašeho klubu.
</VideoText>
</div>
<p className="max-w-2xl text-lg leading-7 text-[rgb(75_85_99)] sm:text-xl sm:leading-8 break-words">
MyClub spojuje MyUIbrix builder, zápasy, týmy, partnery, newslettery a
klubovou administraci do jedné čisté vrstvy připravené na každodenní provoz.
</p>
</div>
<div className="flex flex-col gap-3 sm:flex-row">
<Button
asChild
className="h-12 rounded-full px-6 text-sm shadow-[0_18px_34px_rgba(17,24,39,0.12)]"
>
<a href="#kontakt">
Domluvit ukázku
<ArrowRight className="size-4" />
</a>
</Button>
<Button
asChild
variant="outline"
className="h-12 rounded-full border-[rgba(17,24,39,0.12)] bg-white px-6 text-sm hover:bg-[rgba(108,56,217,0.06)]"
>
<a href="#ukazka">
Projít produktovou vrstvu
<ChevronRight className="size-4" />
</a>
</Button>
</div>
<div className="grid gap-4 sm:grid-cols-3">
{[
'MyUIbrix jako vestavěný editor homepage.',
'Klubová data, obsah a komunikace bez pluginové skládačky.',
'Připravené fungovat vedle stávajícího backendu a publikace.',
].map((item) => (
<div key={item} className="rounded-[1.55rem] border border-[rgba(17,24,39,0.08)] bg-white/88 p-5 backdrop-blur-sm transition-all duration-300 hover:shadow-lg hover:bg-white">
<div className="mb-3 flex items-center gap-2 text-sm font-semibold text-[rgb(17_24_39)]">
<Check className="size-4 text-[rgb(108_56_217)]" />
Přímý benefit
</div>
<p className="text-sm leading-6 text-[rgb(75_85_99)]">{item}</p>
</div>
))}
</div>
</div>
<HeroVisual />
</div>
</section>
<section className="pb-16 pt-8">
<div className="section-shell">
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
{proofPoints.map((item) => (
<Card key={item.title} className="surface-panel-soft border-0 p-6 transition-all duration-300 hover:shadow-xl hover:scale-[1.02]">
<CardHeader className="p-0 pb-4">
<div className="mb-4 flex size-14 items-center justify-center rounded-2xl border border-[rgba(17,24,39,0.08)] bg-white shadow-sm">
<item.icon className="size-6 text-[rgb(108_56_217)]" />
</div>
<CardDescription className="section-label mb-2">{item.eyebrow}</CardDescription>
<CardTitle className="text-xl tracking-[-0.04em] leading-7 text-[rgb(17_24_39)]">{item.title}</CardTitle>
</CardHeader>
<CardContent className="p-0">
<p className="text-sm leading-6 text-[rgb(75_85_99)]">{item.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<section id="platforma" className="scroll-mt-28 py-20">
<div className="section-shell flex flex-col gap-12">
<SectionHeading
kicker="Platforma"
title="Navržené pro klub, který nechce skládat pět různých systémů."
description="Každá vrstva landingu vychází z reálných schopností projektu. Žádná obecná SaaS omáčka, ale konkrétní modulární klubový stack."
/>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
{featureCards.map((item, index) => (
<Card
key={item.title}
className={`
${index % 3 === 1 ? 'surface-panel-secondary border-0' : 'surface-panel border-0'}
p-6 transition-all duration-300 hover:shadow-xl hover:scale-[1.02]
`}
>
<CardHeader className="p-0 pb-4">
<div className="mb-4 flex size-14 items-center justify-center rounded-2xl border border-[rgba(17,24,39,0.08)] bg-white shadow-sm">
<item.icon
className={`
${index % 3 === 1 ? 'size-6 text-[rgb(255_153_51)]' : 'size-6 text-[rgb(108_56_217)]'}
`}
/>
</div>
<CardDescription className="section-label mb-2">{item.eyebrow}</CardDescription>
<CardTitle className="text-xl tracking-[-0.04em] leading-7 text-[rgb(17_24_39)]">{item.title}</CardTitle>
</CardHeader>
<CardContent className="p-0">
<p className="text-sm leading-6 text-[rgb(75_85_99)]">{item.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<section id="ukazka" className="scroll-mt-28 py-20">
<div className="section-shell grid gap-12 xl:grid-cols-[1.08fr_0.92fr]">
<div className="flex flex-col gap-12">
<SectionHeading
kicker="Ukázka produktu"
title="Editorial sports-tech bez generické šablony."
description="Landing používá bílý mód, výraznou typografii a kontrolovanou barevnost. Stejný přístup může nést i veřejný klubový web vystavěný v MyClubu."
/>
<Card className="surface-panel border-0 py-0 transition-all duration-300 hover:shadow-xl">
<CardHeader className="border-b border-[rgba(17,24,39,0.08)] pb-6">
<CardDescription className="section-label">ukázková kompozice</CardDescription>
<CardTitle className="text-2xl tracking-[-0.05em] leading-8">
Homepage builder, který ří rytmus celého klubu
</CardTitle>
</CardHeader>
<CardContent className="grid gap-6 px-6 py-8 sm:grid-cols-[0.95fr_1.05fr]">
<div className="rounded-[1.5rem] border border-[rgba(17,24,39,0.08)] bg-white p-6">
<div className="mb-4 flex items-center justify-between">
<span className="section-label">bloky stránky</span>
<Sparkles className="size-5 text-[rgb(108_56_217)]" />
</div>
<div className="space-y-4">
{[
'Hero s hlavní kampaní',
'Novinky a články',
'Příští zápas + tabulka',
'Sponzoři a bannery',
'Kontakty a mapa',
].map((label, index) => (
<div
key={label}
className="flex items-center gap-4 rounded-[1.1rem] border border-[rgba(17,24,39,0.06)] bg-[rgba(17,24,39,0.02)] px-5 py-4 transition-all duration-200 hover:bg-[rgba(17,24,39,0.04)] hover:shadow-sm"
>
<span className="flex size-8 items-center justify-center rounded-full bg-[rgba(108,56,217,0.08)] text-xs font-semibold text-[rgb(108_56_217)]">
0{index + 1}
</span>
<span className="font-medium text-[rgb(17_24_39)] leading-6">{label}</span>
</div>
))}
</div>
</div>
<div className="rounded-[1.5rem] border border-[rgba(17,24,39,0.08)] bg-[linear-gradient(180deg,rgba(108,56,217,0.08),rgba(255,255,255,0.96))] p-6">
<div className="mb-4 flex items-center justify-between">
<span className="section-label">preview</span>
<LayoutDashboard className="size-5 text-[rgb(17_24_39)]" />
</div>
<div className="grid gap-4">
<div className="rounded-[1.4rem] bg-white p-5">
<div className="h-3 w-2/3 rounded-full bg-[rgba(17,24,39,0.12)] mb-4" />
<div className="grid grid-cols-3 gap-3">
<div className="h-20 rounded-2xl bg-[rgba(108,56,217,0.09)] flex items-center justify-center">
<ImageIcon className="size-6 text-[rgb(108_56_217)/20]" />
</div>
<div className="h-20 rounded-2xl bg-[rgba(255,153,51,0.16)] flex items-center justify-center">
<ImageIcon className="size-6 text-[rgb(255_153_51)/20]" />
</div>
<div className="h-20 rounded-2xl bg-[rgba(17,24,39,0.06)] flex items-center justify-center">
<ImageIcon className="size-6 text-[rgb(17_24_39)/15]" />
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="rounded-[1.25rem] bg-white p-4">
<div className="h-2.5 w-16 rounded-full bg-[rgba(17,24,39,0.12)] mb-4" />
<div className="h-20 rounded-[1rem] bg-[rgba(108,56,217,0.08)] flex items-center justify-center">
<ImageIcon className="size-5 text-[rgb(108_56_217)/15]" />
</div>
</div>
<div className="rounded-[1.25rem] bg-white p-4">
<div className="h-2.5 w-16 rounded-full bg-[rgba(17,24,39,0.12)] mb-4" />
<div className="h-20 rounded-[1rem] bg-[rgba(255,153,51,0.16)] flex items-center justify-center">
<ImageIcon className="size-5 text-[rgb(255_153_51)/15]" />
</div>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
<div className="flex flex-col gap-6">
{operationalPillars.map((item, index) => (
<Card
key={item.title}
className={`
${index === 1 ? 'surface-panel-secondary border-0' : 'surface-panel-soft border-0'}
transition-all duration-300 hover:shadow-xl hover:scale-[1.02]
`}
>
<CardHeader>
<div className="mb-4 flex size-14 items-center justify-center rounded-2xl border border-[rgba(17,24,39,0.08)] bg-white shadow-sm">
<item.icon
className={`
${index === 1 ? 'size-6 text-[rgb(255_153_51)]' : 'size-6 text-[rgb(108_56_217)]'}
`}
/>
</div>
<CardDescription className="section-label mb-2">{item.eyebrow}</CardDescription>
<CardTitle className="text-xl tracking-[-0.04em] leading-7 text-[rgb(17_24_39)]">{item.title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm leading-6 text-[rgb(75_85_99)]">{item.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<section id="workflow" className="scroll-mt-28 py-20">
<div className="section-shell flex flex-col gap-12">
<SectionHeading
kicker="Jak to funguje"
title="Od první identity klubu po každodenní publikaci."
description="Workflow je navržené tak, aby produkt dával smysl vedení klubu, redakci i operativě okolo zápasového provozu."
align="center"
/>
<div className="grid gap-6 lg:grid-cols-4">
{workflowSteps.map((step, index) => (
<Card
key={step.step}
className={`
${index === 1 || index === 3 ? 'surface-panel-secondary border-0' : 'surface-panel border-0'}
transition-all duration-300 hover:shadow-xl hover:scale-[1.02] relative overflow-hidden
`}
>
<div className="absolute inset-0 bg-gradient-to-br from-transparent via-white/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
<CardHeader className="relative z-10">
<div className="flex items-center justify-between gap-4">
<span className="rounded-full bg-white px-4 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] shadow-sm border border-[rgba(17,24,39,0.08)]">
krok {step.step}
</span>
<span className="text-3xl font-semibold tracking-[-0.05em] text-[rgba(17,24,39,0.2)]">
{step.step}
</span>
</div>
<CardTitle className="text-xl tracking-[-0.04em] leading-7 text-[rgb(17_24_39)] mt-4">{step.title}</CardTitle>
</CardHeader>
<CardContent className="relative z-10">
<p className="text-sm leading-6 text-[rgb(75_85_99)]">{step.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<section id="faq" className="scroll-mt-28 py-20">
<div className="section-shell grid gap-12 xl:grid-cols-[0.95fr_1.05fr]">
<SectionHeading
kicker="FAQ"
title="Krátké odpovědi na věci, které padnou nejdřív."
description="Landing je postavený jako publikovatelná poptávková vrstva. Níže jsou odpovědi, které drží směr produktu i technického nasazení."
/>
<Card className="surface-panel border-0 transition-all duration-300 hover:shadow-xl">
<CardContent className="px-8 py-6">
<Accordion type="single" collapsible className="space-y-4">
{faqItems.map((item) => (
<AccordionItem
key={item.question}
value={item.question}
className="border border-[rgba(17,24,39,0.08)] rounded-xl px-6 transition-all duration-200 hover:bg-[rgba(17,24,39,0.02]"
>
<AccordionTrigger className="text-base font-semibold text-[rgb(17_24_39)] hover:text-[rgb(108_56_217)] transition-colors duration-200">
{item.question}
</AccordionTrigger>
<AccordionContent className="text-sm leading-6 text-[rgb(75_85_99)] pt-4">
{item.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</CardContent>
</Card>
</div>
</section>
<section id="kontakt" className="scroll-mt-28 py-20">
<div className="section-shell">
<div className="grid gap-12 rounded-[2rem] border border-[rgba(17,24,39,0.08)] bg-[linear-gradient(135deg,rgba(108,56,217,0.08),rgba(255,255,255,0.98),rgba(255,153,51,0.14))] p-8 shadow-[0_28px_80px_rgba(17,24,39,0.08)] lg:grid-cols-[0.9fr_1.1fr] lg:p-10">
<div className="flex flex-col gap-8">
<Badge className="eyebrow-pill max-w-max">CTA a poptávka</Badge>
<div className="flex flex-col gap-6">
<h2 className="section-title text-[clamp(2.2rem,4vw,4rem)] max-w-lg">
Chcete si projít, jak bude MyClub fungovat pro váš klub?
</h2>
<p className="section-copy max-w-xl">
Pošlete stručný kontext a landing použije existující veřejný endpoint projektu. Tím je hotová
první publikovatelná vrstva bez dalších backend zásahů.
</p>
</div>
<div className="grid gap-4">
{contactChecklist.map((item) => (
<div
key={item}
className="flex items-start gap-4 rounded-[1.35rem] border border-[rgba(17,24,39,0.08)] bg-white/86 px-5 py-5 transition-all duration-300 hover:bg-white hover:shadow-md"
>
<span className="mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-[rgba(108,56,217,0.08)] text-[rgb(108_56_217)]">
<Check className="size-5" />
</span>
<p className="text-sm leading-7 text-[rgb(17_24_39)]">{item}</p>
</div>
))}
</div>
<div className="rounded-[1.45rem] border border-[rgba(17,24,39,0.08)] bg-white/88 p-6 transition-all duration-300 hover:bg-white hover:shadow-md">
<div className="mb-3 flex items-center gap-3 text-sm font-semibold text-[rgb(17_24_39)]">
<MailPlus className="size-5 text-[rgb(255_153_51)]" />
Technická poznámka
</div>
<p className="text-sm leading-7 text-[rgb(75_85_99)]">
V developmentu funguje formulář přes Vite proxy na <code className="px-2 py-1 bg-[rgba(108,56,217,0.08)] rounded-md">localhost:8080</code>. V produkci
může zůstat same-origin nebo využít <code className="px-2 py-1 bg-[rgba(108,56,217,0.08)] rounded-md">VITE_API_BASE_URL</code>.
</p>
</div>
</div>
<Card className="surface-panel border-0 bg-white/92 transition-all duration-300 hover:shadow-xl">
<CardHeader>
<CardDescription className="section-label">pracující formulář</CardDescription>
<CardTitle className="text-2xl tracking-[-0.05em] leading-8">
Pošlete poptávku přes stávající backend
</CardTitle>
</CardHeader>
<CardContent>
<ContactForm />
</CardContent>
</Card>
</div>
</div>
</section>
</main>
<footer className="border-t border-[rgba(17,24,39,0.08)] py-12 bg-gradient-to-b from-white to-[rgba(108,56,217,0.02)]">
<div className="section-shell flex flex-col gap-8 md:flex-row md:items-center md:justify-between">
<div className="flex flex-col gap-3">
<p className="text-xl font-bold tracking-[-0.03em] text-[rgb(17_24_39)]">
MyClub
</p>
<p className="text-sm leading-6 text-[rgb(75_85_99)] max-w-md">
Web, obsah, partneři a klubový provoz bez generické CMS skládačky.
</p>
</div>
<div className="flex flex-wrap items-center gap-6 text-sm font-medium text-[rgb(75_85_99)]">
{navItems.map((item) => (
<a
key={item.href}
href={item.href}
className="transition-all duration-200 hover:text-[rgb(108_56_217)] hover:translate-y-[-1px]"
>
{item.label}
</a>
))}
</div>
</div>
</footer>
</div>
)
}
@@ -0,0 +1,190 @@
import { useState } from 'react'
import { zodResolver } from '@hookform/resolvers/zod'
import axios from 'axios'
import { ArrowRight, LoaderCircle } from 'lucide-react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { submitContactForm } from '@/lib/api'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
const contactSchema = z.object({
name: z.string().min(2, 'Zadejte prosím jméno nebo název klubu.'),
email: z.email('Zadejte prosím platný e-mail.'),
subject: z.string().min(3, 'Napište stručné téma poptávky.'),
message: z.string().min(24, 'Doplňte prosím alespoň krátký kontext, co chcete řešit.'),
})
type ContactValues = z.infer<typeof contactSchema>
const defaultValues: ContactValues = {
name: '',
email: '',
subject: 'Mám zájem o ukázku MyClubu',
message: '',
}
type FormStatus =
| { type: 'success'; message: string }
| { type: 'error'; message: string }
| null
export function ContactForm() {
const [status, setStatus] = useState<FormStatus>(null)
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<ContactValues>({
resolver: zodResolver(contactSchema),
defaultValues,
})
async function onSubmit(values: ContactValues) {
setStatus(null)
try {
await submitContactForm(values)
reset(defaultValues)
setStatus({
type: 'success',
message:
'Poptávka byla odeslána. Pokud je backend správně nakonfigurovaný, zpráva právě dorazila do klubové kontaktní vrstvy.',
})
} catch (error) {
let message =
'Odeslání se nepodařilo. Zkontrolujte, že běží backend a že endpoint /api/v1/contact přijímá veřejné formuláře.'
if (axios.isAxiosError(error)) {
const serverMessage =
typeof error.response?.data?.error === 'string'
? error.response.data.error
: undefined
if (serverMessage) {
if (/failed to save message/i.test(serverMessage)) {
message =
'Server zprávu přijal, ale nepodařilo se ji uložit. Zkontrolujte databázi a nastavení kontaktního formuláře na backendu.'
} else if (/invalid payload/i.test(serverMessage)) {
message = 'Server odmítl odeslaná data. Zkontrolujte prosím vyplněná pole.'
} else if (/valid email is required/i.test(serverMessage)) {
message = 'Zadejte prosím platný e-mail.'
} else {
message = serverMessage
}
} else if (error.code === 'ECONNABORTED') {
message = 'Server neodpověděl včas. Zkuste odeslání znovu nebo zkontrolujte backend.'
} else if (!error.response) {
message = 'Nepodařilo se spojit s API. V developmentu ověřte proxy nebo VITE_API_BASE_URL.'
}
}
setStatus({ type: 'error', message })
}
}
return (
<form className="flex flex-col gap-5" onSubmit={handleSubmit(onSubmit)} noValidate>
<div className="grid gap-5 sm:grid-cols-2">
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-[rgb(17_24_39)]" htmlFor="name">
Jméno / klub
</label>
<Input
id="name"
placeholder="Například FK Example / Jan Novák"
aria-invalid={errors.name ? true : undefined}
className="h-12 rounded-2xl border-[rgba(17,24,39,0.1)] bg-white px-4 text-[rgb(17_24_39)] placeholder:text-[rgba(75,85,99,0.7)]"
{...register('name')}
/>
{errors.name ? <p className="form-feedback">{errors.name.message}</p> : null}
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-[rgb(17_24_39)]" htmlFor="email">
E-mail
</label>
<Input
id="email"
type="email"
placeholder="vas@email.cz"
aria-invalid={errors.email ? true : undefined}
className="h-12 rounded-2xl border-[rgba(17,24,39,0.1)] bg-white px-4 text-[rgb(17_24_39)] placeholder:text-[rgba(75,85,99,0.7)]"
{...register('email')}
/>
{errors.email ? <p className="form-feedback">{errors.email.message}</p> : null}
</div>
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-[rgb(17_24_39)]" htmlFor="subject">
Co chcete řešit
</label>
<Input
id="subject"
aria-invalid={errors.subject ? true : undefined}
className="h-12 rounded-2xl border-[rgba(17,24,39,0.1)] bg-white px-4 text-[rgb(17_24_39)] placeholder:text-[rgba(75,85,99,0.7)]"
{...register('subject')}
/>
{errors.subject ? <p className="form-feedback">{errors.subject.message}</p> : null}
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-[rgb(17_24_39)]" htmlFor="message">
Krátký kontext
</label>
<Textarea
id="message"
rows={6}
placeholder="Popište klub, stávající web, jak dnes funguje obsah a co má nová platforma zjednodušit."
aria-invalid={errors.message ? true : undefined}
className="min-h-36 rounded-[1.35rem] border-[rgba(17,24,39,0.1)] bg-white px-4 py-3 text-[rgb(17_24_39)] placeholder:text-[rgba(75,85,99,0.7)]"
{...register('message')}
/>
{errors.message ? <p className="form-feedback">{errors.message.message}</p> : null}
</div>
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<Button
type="submit"
className="h-12 rounded-full px-6 text-sm shadow-[0_16px_32px_rgba(17,24,39,0.12)]"
disabled={isSubmitting}
>
{isSubmitting ? (
<>
<LoaderCircle className="size-4 animate-spin" />
Odesílám
</>
) : (
<>
Domluvit ukázku
<ArrowRight className="size-4" />
</>
)}
</Button>
<p className="max-w-xs text-sm leading-6 text-[rgb(75_85_99)]">
Formulář používá stávající veřejný endpoint projektu. V produkci stačí stejné origin API nebo
nastavit <code>VITE_API_BASE_URL</code>.
</p>
</div>
<div aria-live="polite" className="min-h-6">
{status ? (
<p
className={
status.type === 'success'
? 'rounded-3xl border border-[rgba(108,56,217,0.15)] bg-[rgba(108,56,217,0.07)] px-4 py-3 text-sm leading-6 text-[rgb(17_24_39)]'
: 'rounded-3xl border border-[rgba(255,153,51,0.24)] bg-[rgba(255,153,51,0.12)] px-4 py-3 text-sm leading-6 text-[rgb(17_24_39)]'
}
>
{status.message}
</p>
) : null}
</div>
</form>
)
}
@@ -0,0 +1,205 @@
import {
ArrowUpRight,
CalendarRange,
ChartColumnIncreasing,
Layers3,
MailPlus,
Trophy,
Image as ImageIcon,
} from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { VideoText } from '@/components/ui/video-text'
export function HeroVisual() {
return (
<div className="relative mx-auto w-full max-w-[680px]">
<div className="hero-halo hero-halo-primary absolute -left-16 top-16 size-56" />
<div className="hero-halo hero-halo-secondary absolute -right-12 top-4 size-52" />
<Card className="surface-panel relative overflow-hidden rounded-[2rem] border-0 py-0 transition-all duration-500 hover:shadow-2xl">
<CardHeader className="border-b border-[rgba(17,24,39,0.08)] px-8 py-6">
<div className="flex items-center justify-between gap-4">
<div className="flex-1">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-[rgb(108_56_217)] mb-3">
produktová ukázka
</p>
<CardTitle className="text-2xl tracking-[-0.04em] leading-8">
Řídicí vrstva pro klubový web
</CardTitle>
</div>
<Badge
variant="outline"
className="hidden border-[rgba(17,24,39,0.08)] bg-white px-4 py-2 text-[rgb(75_85_99)] sm:inline-flex shadow-sm"
>
white mode only
</Badge>
</div>
<CardDescription className="max-w-xl text-[rgb(75_85_99)] mt-3 leading-6">
MyUIbrix, klubový obsah, partneři i matchday přehled v jedné kompozici.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-6 px-8 py-8 lg:grid-cols-[1.08fr_0.92fr]">
<div className="space-y-5">
<div className="mock-window dashboard-grid rounded-[1.75rem] p-5">
<div className="mb-5 flex items-center justify-between gap-4">
<div className="flex gap-3">
<span className="size-3 rounded-full bg-[rgba(108,56,217,0.45)] shadow-sm" />
<span className="size-3 rounded-full bg-[rgba(255,153,51,0.45)] shadow-sm" />
<span className="size-3 rounded-full bg-[rgba(17,24,39,0.18)] shadow-sm" />
</div>
<div className="rounded-full bg-white px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] shadow-sm border border-[rgba(17,24,39,0.08)]">
homepage builder
</div>
</div>
<div className="grid gap-4">
<div className="rounded-[1.3rem] border border-[rgba(108,56,217,0.16)] bg-[rgba(108,56,217,0.07)] p-5">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-3 text-sm font-semibold text-[rgb(17_24_39)]">
<Layers3 className="size-5 text-[rgb(108_56_217)]" />
Hero + novinky + zápasy
</div>
<span className="rounded-full bg-white px-3 py-1.5 text-[11px] font-semibold text-[rgb(108_56_217)] shadow-sm border border-[rgba(108,56,217,0.16)]">
live preview
</span>
</div>
<div className="space-y-3">
<div className="h-3 w-11/12 rounded-full bg-white/90 shadow-sm" />
<div className="h-3 w-8/12 rounded-full bg-white/75 shadow-sm" />
<div className="grid grid-cols-3 gap-3 pt-2">
<div className="h-20 rounded-2xl bg-white/85 shadow-sm flex items-center justify-center relative overflow-hidden group">
<VideoText
src="https://cdn.magicui.design/ocean-small.webm"
className="absolute inset-0"
fontSize={8}
>
<ImageIcon className="size-8 text-white/80" />
</VideoText>
</div>
<div className="h-20 rounded-2xl bg-white/70 shadow-sm flex items-center justify-center relative overflow-hidden group">
<VideoText
src="https://cdn.magicui.design/ocean-small.webm"
className="absolute inset-0"
fontSize={8}
>
<ImageIcon className="size-8 text-white/80" />
</VideoText>
</div>
<div className="h-20 rounded-2xl bg-white/85 shadow-sm flex items-center justify-center relative overflow-hidden group">
<VideoText
src="https://cdn.magicui.design/ocean-small.webm"
className="absolute inset-0"
fontSize={8}
>
<ImageIcon className="size-8 text-white/80" />
</VideoText>
</div>
</div>
</div>
</div>
<div className="grid gap-3 sm:grid-cols-3">
<div className="rounded-[1.2rem] border border-[rgba(17,24,39,0.08)] bg-white p-4 transition-all duration-300 hover:shadow-md hover:scale-[1.02]">
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] mb-3">
články
</div>
<div className="mt-2 text-xl font-semibold tracking-[-0.04em] text-[rgb(17_24_39)]">
redakce
</div>
</div>
<div className="rounded-[1.2rem] border border-[rgba(17,24,39,0.08)] bg-white p-4 transition-all duration-300 hover:shadow-md hover:scale-[1.02]">
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] mb-3">
partneři
</div>
<div className="mt-2 text-xl font-semibold tracking-[-0.04em] text-[rgb(17_24_39)]">
bannery
</div>
</div>
<div className="rounded-[1.2rem] border border-[rgba(17,24,39,0.08)] bg-white p-4 transition-all duration-300 hover:shadow-md hover:scale-[1.02]">
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] mb-3">
komunikace
</div>
<div className="mt-2 text-xl font-semibold tracking-[-0.04em] text-[rgb(17_24_39)]">
newsletter
</div>
</div>
</div>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="metric-chip transition-all duration-300 hover:shadow-md hover:scale-[1.02]">
<CalendarRange className="size-5 text-[rgb(108_56_217)]" />
<span className="text-sm leading-5">Zápasy a tabulky v klubovém layoutu</span>
</div>
<div className="metric-chip transition-all duration-300 hover:shadow-md hover:scale-[1.02]">
<MailPlus className="size-5 text-[rgb(255_153_51)]" />
<span className="text-sm leading-5">Kontakty a newsletter bez externí skládačky</span>
</div>
</div>
</div>
<div className="space-y-5">
<div className="rounded-[1.75rem] border border-[rgba(17,24,39,0.08)] bg-white p-6 shadow-[0_20px_40px_rgba(17,24,39,0.06)] transition-all duration-300 hover:shadow-xl">
<div className="mb-5 flex items-center justify-between">
<div className="flex items-center gap-3 text-sm font-semibold text-[rgb(17_24_39)]">
<Trophy className="size-5 text-[rgb(255_153_51)]" />
Match center
</div>
<span className="text-xs font-semibold uppercase tracking-[0.18em] text-[rgb(75_85_99)]">
připraveno na víkend
</span>
</div>
<div className="space-y-3">
{[
['1. tým', 'sobota 16:30'],
['Dorost U19', 'neděle 10:15'],
['Ženy', 'neděle 14:00'],
].map(([label, time]) => (
<div
key={label}
className="flex items-center justify-between rounded-[1.1rem] border border-[rgba(17,24,39,0.07)] bg-[rgba(17,24,39,0.02)] px-4 py-3 transition-all duration-200 hover:bg-[rgba(17,24,39,0.04)] hover:shadow-sm"
>
<span className="font-medium text-[rgb(17_24_39)]">{label}</span>
<span className="text-sm text-[rgb(75_85_99)]">{time}</span>
</div>
))}
</div>
</div>
<div className="rounded-[1.75rem] border border-[rgba(17,24,39,0.08)] bg-[linear-gradient(180deg,rgba(255,153,51,0.12),rgba(255,255,255,0.98))] p-6 shadow-[0_20px_40px_rgba(17,24,39,0.06)] transition-all duration-300 hover:shadow-xl">
<div className="mb-5 flex items-center justify-between">
<div className="flex items-center gap-3 text-sm font-semibold text-[rgb(17_24_39)]">
<ChartColumnIncreasing className="size-5 text-[rgb(108_56_217)]" />
Přehled vedení
</div>
<ArrowUpRight className="size-4 text-[rgb(17_24_39)]" />
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="rounded-[1.2rem] bg-white/80 p-4 transition-all duration-300 hover:bg-white hover:shadow-sm min-h-[100px] flex flex-col justify-between">
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] mb-2">
obsah
</div>
<div className="text-lg font-bold tracking-[-0.02em] text-[rgb(17_24_39)] leading-tight">
pod kontrolou
</div>
</div>
<div className="rounded-[1.2rem] bg-white/80 p-4 transition-all duration-300 hover:bg-white hover:shadow-sm min-h-[100px] flex flex-col justify-between">
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-[rgb(75_85_99)] mb-2">
partneři
</div>
<div className="text-lg font-bold tracking-[-0.02em] text-[rgb(17_24_39)] leading-tight">
v publikaci
</div>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
)
}
@@ -0,0 +1,28 @@
import { cn } from '@/lib/utils'
type SectionHeadingProps = {
kicker: string
title: string
description: string
align?: 'left' | 'center'
}
export function SectionHeading({
kicker,
title,
description,
align = 'left',
}: SectionHeadingProps) {
return (
<div
className={cn(
'flex flex-col gap-4',
align === 'center' && 'mx-auto max-w-3xl text-center'
)}
>
<span className="section-kicker">{kicker}</span>
<h2 className="section-title text-[clamp(2rem,4vw,3.55rem)]">{title}</h2>
<p className="section-copy max-w-3xl">{description}</p>
</div>
)
}

Some files were not shown because too many files have changed in this diff Show More