diff --git a/.gitignore b/.gitignore index 6080f85..6fd53f2 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,5 @@ desloppify-out/ # Analysis output graphify-out/ output/ +.vercel +.env* diff --git a/README.md b/README.md index 33aa155..81e2562 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,10 @@ billing machinery underneath. Deployment targets: -- frontend on Vercel +- frontend on Vercel — `bookra-frontend` serves `www.bookra.eu` (landing only, + pre-launch: signup CTAs are mailto and app routes redirect to `/`); + `bookrademo` serves `demo.bookra.eu` (full app). The split is enforced by + hostname in `apps/frontend/src/lib/app-host.ts`. - backend on Railway - Neon Postgres + Neon Auth - Stripe billing (checkout, customer portal, webhooks, SMS usage invoices) diff --git a/apps/frontend/.gitignore b/apps/frontend/.gitignore new file mode 100644 index 0000000..245259b --- /dev/null +++ b/apps/frontend/.gitignore @@ -0,0 +1,2 @@ +.vercel +.env* diff --git a/apps/frontend/index.html b/apps/frontend/index.html index 2d33bc2..f5b55e9 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -10,12 +10,40 @@ Bookra — Jednoduchý rezervační software + + + + + + + + + + + + + + + + diff --git a/apps/frontend/public/og.png b/apps/frontend/public/og.png new file mode 100644 index 0000000..9626319 Binary files /dev/null and b/apps/frontend/public/og.png differ diff --git a/apps/frontend/public/robots.txt b/apps/frontend/public/robots.txt new file mode 100644 index 0000000..4ac511f --- /dev/null +++ b/apps/frontend/public/robots.txt @@ -0,0 +1,8 @@ +User-agent: * +Allow: / +Disallow: /dashboard +Disallow: /book/ +Disallow: /manage/ +Disallow: /auth/ + +Sitemap: https://bookra.eu/sitemap.xml diff --git a/apps/frontend/public/sitemap.xml b/apps/frontend/public/sitemap.xml new file mode 100644 index 0000000..199844a --- /dev/null +++ b/apps/frontend/public/sitemap.xml @@ -0,0 +1,9 @@ + + + https://bookra.eu/1.0 + https://bookra.eu/pricing0.9 + https://bookra.eu/about + https://bookra.eu/contact + https://bookra.eu/privacy + https://bookra.eu/terms + diff --git a/apps/frontend/src/App.tsx b/apps/frontend/src/App.tsx index 4bb72e3..270f710 100644 --- a/apps/frontend/src/App.tsx +++ b/apps/frontend/src/App.tsx @@ -6,16 +6,27 @@ import { I18nProvider } from "./providers/i18n-provider"; import { ThemeProvider } from "./providers/theme-provider"; import { Shell } from "./components/shell"; +const ROUTE_TITLES: Record = { + "/pricing": "Bookra - Ceník", + "/about": "Bookra - O nás", + "/contact": "Bookra - Kontakt", + "/privacy": "Bookra - Ochrana soukromí", + "/terms": "Bookra - Obchodní podmínky", +}; + // ScrollToTop component that resets scroll position on route change const ScrollToTop = () => { const location = useLocation(); - + createEffect(() => { - // Reset scroll position whenever the pathname changes - location.pathname; + // Reset scroll position and document title whenever the pathname changes + const path = location.pathname; window.scrollTo({ top: 0, left: 0, behavior: "instant" }); + document.title = ROUTE_TITLES[path] ?? (path.startsWith("/dashboard") || path.startsWith("/book") || path.startsWith("/manage") + ? "Bookra" + : "Bookra - Jednoduchý rezervační software"); }); - + return null; }; diff --git a/apps/frontend/src/components/shell.tsx b/apps/frontend/src/components/shell.tsx index 309e8c5..5843090 100644 --- a/apps/frontend/src/components/shell.tsx +++ b/apps/frontend/src/components/shell.tsx @@ -3,6 +3,7 @@ import { ParentComponent, Show, createSignal, onMount, onCleanup } from "solid-j import { useAuth } from "../providers/auth-provider"; import { useI18n } from "../providers/i18n-provider"; import { useTheme } from "../providers/theme-provider"; +import { isAppHost } from "../lib/app-host"; import { BookraCharacter } from "./bookra-character"; import { Button, @@ -96,10 +97,7 @@ export const Shell: ParentComponent = (props) => { ]; // Demo mode detection - const isDemoMode = () => { - const hostname = window.location.hostname; - return hostname.includes("demo") || hostname === "localhost" || hostname === "127.0.0.1"; - }; + const isDemoMode = isAppHost; // Listen for custom event to open auth dialog from dashboard onMount(() => { @@ -284,12 +282,9 @@ export const Shell: ParentComponent = (props) => { { - setAuthMode("sign-in"); - setSignInOpen(true); - }} + onClick={() => { window.location.href = "https://demo.bookra.eu"; }} > - {i18n.t("auth.signIn")} + {i18n.locale() === 'cs' ? 'Vyzkoušet demo' : 'Try demo'} }> }> @@ -388,15 +401,15 @@ const PricingRoute = () => { {isCs() ? "Stále si nejste jistí?" : "Still not sure?"}

- {isCs() - ? "Začněte s bezplatným 15denním trial a rozhodněte se později." - : "Start with a free 15-day trial and decide later."} + {isCs() + ? "Bookra se spouští brzy. Nechte nám e-mail a po spuštění dostanete 15denní trial zdarma." + : "Bookra launches soon. Leave us your email and get a free 15-day trial at launch."}

- {isCs() ? "Začít zdarma" : "Start for free"} + {isAppHost() ? (isCs() ? "Začít zdarma" : "Start for free") : waitlistLabel()} diff --git a/apps/frontend/tsconfig.tsbuildinfo b/apps/frontend/tsconfig.tsbuildinfo index fa50d38..5a50941 100644 --- a/apps/frontend/tsconfig.tsbuildinfo +++ b/apps/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/App.tsx","./src/main.tsx","./src/components/animated-list.tsx","./src/components/bookra-character.tsx","./src/components/calendar-feed.tsx","./src/components/dashboard-mockup.tsx","./src/components/floating-dock.tsx","./src/components/hover-feature-cards.tsx","./src/components/index.ts","./src/components/integration-modal.tsx","./src/components/location-map.tsx","./src/components/pinned-list.tsx","./src/components/shell.tsx","./src/components/sms-settings.tsx","./src/components/video-player.tsx","./src/components/widget-builder.tsx","./src/components/dashboard/activity-timeline.tsx","./src/components/dashboard/calendar-view.tsx","./src/components/dashboard/export-csv-button.tsx","./src/components/dashboard/icons.tsx","./src/components/dashboard/kpi-card.tsx","./src/components/dashboard/notification-dropdown.tsx","./src/components/dashboard/revenue-chart.tsx","./src/components/dashboard/types.ts","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/dialog.tsx","./src/components/ui/index.ts","./src/components/ui/input.tsx","./src/components/ui/select.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/tooltip.tsx","./src/lib/api-client.ts","./src/lib/map.ts","./src/lib/sentry.ts","./src/lib/types.ts","./src/providers/auth-provider.tsx","./src/providers/i18n-provider.tsx","./src/providers/theme-provider.tsx","./src/routes/about-route.tsx","./src/routes/auth-callback-route.tsx","./src/routes/booking-manage-route.tsx","./src/routes/contact-route.tsx","./src/routes/home-route.tsx","./src/routes/legal-route.tsx","./src/routes/not-found-route.tsx","./src/routes/pricing-route.tsx","./src/routes/public-booking-route.tsx","./src/routes/dashboard/billing-page.tsx","./src/routes/dashboard/bookings-page.tsx","./src/routes/dashboard/customers-page.tsx","./src/routes/dashboard/dashboard-data.ts","./src/routes/dashboard/layout.tsx","./src/routes/dashboard/overview-page.tsx","./src/routes/dashboard/services-page.tsx","./src/routes/dashboard/settings-page.tsx","./src/routes/dashboard/staff-page.tsx","./src/routes/dashboard/zones-page.tsx","./vite.config.ts"],"version":"5.9.3"} \ No newline at end of file +{"root":["./src/App.tsx","./src/main.tsx","./src/components/animated-list.tsx","./src/components/bookra-character.tsx","./src/components/calendar-feed.tsx","./src/components/dashboard-mockup.tsx","./src/components/floating-dock.tsx","./src/components/hover-feature-cards.tsx","./src/components/index.ts","./src/components/integration-modal.tsx","./src/components/location-map.tsx","./src/components/pinned-list.tsx","./src/components/shell.tsx","./src/components/sms-settings.tsx","./src/components/video-player.tsx","./src/components/widget-builder.tsx","./src/components/dashboard/activity-timeline.tsx","./src/components/dashboard/calendar-view.tsx","./src/components/dashboard/export-csv-button.tsx","./src/components/dashboard/icons.tsx","./src/components/dashboard/kpi-card.tsx","./src/components/dashboard/notification-dropdown.tsx","./src/components/dashboard/revenue-chart.tsx","./src/components/dashboard/types.ts","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/dialog.tsx","./src/components/ui/index.ts","./src/components/ui/input.tsx","./src/components/ui/select.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/tooltip.tsx","./src/lib/api-client.ts","./src/lib/app-host.ts","./src/lib/map.ts","./src/lib/sentry.ts","./src/lib/types.ts","./src/providers/auth-provider.tsx","./src/providers/i18n-provider.tsx","./src/providers/theme-provider.tsx","./src/routes/about-route.tsx","./src/routes/auth-callback-route.tsx","./src/routes/booking-manage-route.tsx","./src/routes/contact-route.tsx","./src/routes/home-route.tsx","./src/routes/legal-route.tsx","./src/routes/not-found-route.tsx","./src/routes/pricing-route.tsx","./src/routes/public-booking-route.tsx","./src/routes/dashboard/billing-page.tsx","./src/routes/dashboard/bookings-page.tsx","./src/routes/dashboard/customers-page.tsx","./src/routes/dashboard/dashboard-data.ts","./src/routes/dashboard/layout.tsx","./src/routes/dashboard/overview-page.tsx","./src/routes/dashboard/services-page.tsx","./src/routes/dashboard/settings-page.tsx","./src/routes/dashboard/staff-page.tsx","./src/routes/dashboard/zones-page.tsx","./vite.config.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/apps/frontend/vercel.json b/apps/frontend/vercel.json new file mode 100644 index 0000000..0f32683 --- /dev/null +++ b/apps/frontend/vercel.json @@ -0,0 +1,3 @@ +{ + "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] +}