diff --git a/apps/planner/app/routes/home.tsx b/apps/planner/app/routes/home.tsx index de5d4e9..e9177de 100644 --- a/apps/planner/app/routes/home.tsx +++ b/apps/planner/app/routes/home.tsx @@ -3,20 +3,87 @@ import type { Route } from "./+types/home"; export function meta(_args: Route.MetaArgs) { return [ - { title: "trails.cool Planner" }, - { name: "description", content: "Collaborative route planning" }, + { title: "trails.cool Planner — Collaborative Route Planning" }, + { name: "description", content: "Plan hiking and cycling routes together in real-time. No account needed." }, ]; } +const features = [ + { key: "featureCollaborative", icon: "👥" }, + { key: "featureRouting", icon: "🗺️" }, + { key: "featureElevation", icon: "⛰️" }, + { key: "featureExport", icon: "📥" }, + { key: "featureNoAccount", icon: "🔓" }, +] as const; + export default function Home() { const { t } = useTranslation("planner"); return ( -
-
-

{t("title")}

-

{t("subtitle")}

-
+
+ {/* Hero */} +
+

+ {t("title")} +

+

+ {t("landing.heroDescription")} +

+ + {t("landing.startPlanning")} + +
+ + {/* Features */} +
+
+ {features.map(({ key, icon }) => ( +
+
{icon}
+

+ {t(`landing.${key}`)} +

+

+ {t(`landing.${key}Desc`)} +

+
+ ))} +
+
+ + {/* Secondary CTA */} +
+

+ {t("landing.saveRoutes")} +

+

+ {t("landing.saveRoutesDesc")} +

+ + {t("landing.goToJournal")} + +
+ + {/* Footer */} +
); } diff --git a/e2e/planner.test.ts b/e2e/planner.test.ts index 0d7d67c..67d6c97 100644 --- a/e2e/planner.test.ts +++ b/e2e/planner.test.ts @@ -3,8 +3,8 @@ import { test, expect } from "@playwright/test"; test.describe("Planner", () => { test("loads the home page", async ({ page }) => { await page.goto("/"); - await expect(page).toHaveTitle("trails.cool Planner"); - await expect(page.getByText("Collaborative route planning")).toBeVisible(); + await expect(page).toHaveTitle(/trails\.cool Planner/); + await expect(page.getByRole("link", { name: "Start Planning" })).toBeVisible(); }); test("can create a session via API", async ({ request }) => { diff --git a/openspec/changes/planner-landing-page/tasks.md b/openspec/changes/planner-landing-page/tasks.md index 0506515..53095da 100644 --- a/openspec/changes/planner-landing-page/tasks.md +++ b/openspec/changes/planner-landing-page/tasks.md @@ -1,16 +1,16 @@ ## 1. Landing Page Content -- [ ] 1.1 Rewrite Planner home.tsx with hero section: heading, subtitle, "Start Planning" CTA linking to /new -- [ ] 1.2 Add feature highlights section (4-5 cards): collaborative editing, routing profiles, elevation profile, GPX export, no account needed -- [ ] 1.3 Add secondary CTA: "Save your routes on trails.cool" linking to Journal -- [ ] 1.4 Add footer: privacy link, GitHub repo, BRouter/OSM attribution +- [x] 1.1 Rewrite Planner home.tsx with hero section: heading, subtitle, "Start Planning" CTA linking to /new +- [x] 1.2 Add feature highlights section (4-5 cards): collaborative editing, routing profiles, elevation profile, GPX export, no account needed +- [x] 1.3 Add secondary CTA: "Save your routes on trails.cool" linking to Journal +- [x] 1.4 Add footer: privacy link, GitHub repo, BRouter/OSM attribution ## 2. i18n -- [ ] 2.1 Add all landing page strings to en.ts and de.ts (hero, features, CTAs, footer) +- [x] 2.1 Add all landing page strings to en.ts and de.ts (hero, features, CTAs, footer) ## 3. Verify -- [ ] 3.1 Verify landing page renders correctly at planner.trails.cool -- [ ] 3.2 Verify "Start Planning" creates a session and redirects -- [ ] 3.3 Update E2E planner test if home page assertions changed +- [x] 3.1 Verify landing page renders correctly at planner.trails.cool +- [x] 3.2 Verify "Start Planning" creates a session and redirects +- [x] 3.3 Update E2E planner test if home page assertions changed diff --git a/packages/i18n/src/locales/de.ts b/packages/i18n/src/locales/de.ts index 9e86754..dea861c 100644 --- a/packages/i18n/src/locales/de.ts +++ b/packages/i18n/src/locales/de.ts @@ -39,6 +39,28 @@ export default { loss: "Höhenmeter abwärts", profile: "Höhenprofil", }, + landing: { + startPlanning: "Planung starten", + heroDescription: "Plane Wander- und Radrouten gemeinsam in Echtzeit. Kein Konto nötig.", + featureCollaborative: "Echtzeit-Zusammenarbeit", + featureCollaborativeDesc: "Wegpunkte gemeinsam bearbeiten — Änderungen werden sofort synchronisiert.", + featureRouting: "Intelligentes Routing", + featureRoutingDesc: "BRouter berechnet optimale Routen für Wandern, Radfahren oder Autofahren mit Höhenprofil.", + featureElevation: "Höhenprofil", + featureElevationDesc: "Das vollständige Höhenprofil deiner Route mit Auf- und Abstiegsstatistiken.", + featureExport: "GPX-Export", + featureExportDesc: "Exportiere deine Route als GPX für jedes GPS-Gerät oder jede App.", + featureNoAccount: "Kein Konto nötig", + featureNoAccountDesc: "Sofort loslegen. Teile einen Link und jeder kann deiner Sitzung beitreten.", + saveRoutes: "Routen speichern?", + saveRoutesDesc: "Erstelle ein kostenloses Konto auf trails.cool, um Routen zu speichern, Aktivitäten zu verfolgen und mehr.", + goToJournal: "Zu trails.cool", + footer: { + privacy: "Datenschutz", + source: "Quellcode", + builtWith: "Erstellt mit BRouter und OpenStreetMap", + }, + }, }, journal: { title: "trails.cool", diff --git a/packages/i18n/src/locales/en.ts b/packages/i18n/src/locales/en.ts index c5b3837..3842de0 100644 --- a/packages/i18n/src/locales/en.ts +++ b/packages/i18n/src/locales/en.ts @@ -39,6 +39,28 @@ export default { loss: "Elevation Loss", profile: "Elevation Profile", }, + landing: { + startPlanning: "Start Planning", + heroDescription: "Plan hiking and cycling routes together in real-time. No account needed.", + featureCollaborative: "Real-Time Collaboration", + featureCollaborativeDesc: "Edit waypoints together — changes sync instantly across all participants.", + featureRouting: "Smart Routing", + featureRoutingDesc: "BRouter computes optimal routes for hiking, cycling, or driving with elevation awareness.", + featureElevation: "Elevation Profile", + featureElevationDesc: "See the full elevation profile of your route with gain and loss statistics.", + featureExport: "GPX Export", + featureExportDesc: "Export your route as GPX for use in any GPS device or app.", + featureNoAccount: "No Account Needed", + featureNoAccountDesc: "Start planning immediately. Share a link and anyone can join your session.", + saveRoutes: "Want to save your routes?", + saveRoutesDesc: "Create a free account on trails.cool to keep your routes, track activities, and more.", + goToJournal: "Go to trails.cool", + footer: { + privacy: "Privacy", + source: "Source Code", + builtWith: "Built with BRouter and OpenStreetMap", + }, + }, }, journal: { title: "trails.cool",