Add legal pages, ToS acceptance, and alpha banner

- Journal: Impressum (§5 TMG), Terms of Service, GDPR privacy page
- Registration flow: required ToS checkbox, termsAcceptedAt persisted
- Alpha banner on Journal (always visible); alpha badge on Planner hero
- Footer with legal links + GitHub on both apps
- Reduce PII: sendDefaultPii=false, Sentry init only after login (Journal)
- Drop Sentry from Planner (no login, no consent possible)
- Drop localStorage caching from i18n client detection
- Sync SSR i18n resources each request so locale edits HMR without restart

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-18 00:08:48 +02:00
parent 6c1cd23358
commit cc0f44258a
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
24 changed files with 773 additions and 206 deletions

View file

@ -1,30 +1,8 @@
import * as Sentry from "@sentry/react";
import { useEffect } from "react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import { HydratedRouter } from "react-router/dom";
import { useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from "react-router";
import { initI18nClient } from "@trails-cool/i18n";
const sentryEnvironment = import.meta.env.VITE_SENTRY_ENVIRONMENT ??
(import.meta.env.PROD ? "production" : "development");
Sentry.init({
dsn: "https://5215134cd78d5e6c199e29300b8425af@o4509530546634752.ingest.de.sentry.io/4511102546608208",
integrations: [
Sentry.reactRouterV7BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
environment: sentryEnvironment,
tracesSampleRate: sentryEnvironment === "ci" ? 0 : 1.0,
enabled: import.meta.env.PROD && sentryEnvironment !== "ci",
});
initI18nClient();
startTransition(() => {

View file

@ -61,6 +61,9 @@ export default function Home() {
<div className="flex h-full flex-col overflow-y-auto">
{/* Hero */}
<section className="flex flex-1 flex-col items-center justify-center px-4 py-16">
<span className="mb-4 inline-block rounded-full bg-amber-100 px-3 py-1 text-xs font-medium uppercase tracking-wide text-amber-800">
{t("landing.footer.alpha")}
</span>
<h1 className="text-5xl font-bold tracking-tight text-gray-900 sm:text-6xl">
{t("title")}
</h1>
@ -129,11 +132,20 @@ export default function Home() {
{/* Footer */}
<footer className="border-t border-gray-200 px-4 py-6">
<div className="mx-auto flex max-w-4xl flex-wrap items-center justify-between gap-4 text-sm text-gray-400">
<span>{t("landing.footer.builtWith")}</span>
<span>
{t("landing.footer.builtWith")}
<span className="ml-2 text-xs">· {t("landing.footer.alpha")}</span>
</span>
<div className="flex gap-4">
<a href="https://trails.cool/privacy" className="hover:text-gray-600">
<a href="https://trails.cool/legal/imprint" className="hover:text-gray-600">
{t("landing.footer.imprint")}
</a>
<a href="https://trails.cool/legal/privacy" className="hover:text-gray-600">
{t("landing.footer.privacy")}
</a>
<a href="https://trails.cool/legal/terms" className="hover:text-gray-600">
{t("landing.footer.terms")}
</a>
<a href="https://github.com/trails-cool/trails" className="hover:text-gray-600">
{t("landing.footer.source")}
</a>