diff --git a/src/routes/[lang]/onlineboard/[params]/page.tsx b/src/routes/[lang]/onlineboard/[params]/page.tsx
new file mode 100644
index 00000000..b876736d
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/[params]/page.tsx
@@ -0,0 +1,37 @@
+/**
+ * Online Board flight details route.
+ *
+ * Parses flight ID from URL, renders detailed flight info.
+ * URL: /{lang}/onlineboard/{carrier}{flightNumber}-{yyyyMMdd}
+ */
+
+import { lazy, Suspense } from "react";
+import { useParams } from "@modern-js/runtime/router";
+import { parseFlightUrlParams } from "@/features/online-board/url.js";
+import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
+
+const OnlineBoardDetailsPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardDetailsPage.js").then(
+ (m) => ({ default: m.OnlineBoardDetailsPage }),
+ ),
+);
+
+export default function FlightDetailsPage(): JSX.Element {
+ const routeParams = useParams<{ params: string }>();
+ const raw = routeParams.params ?? "";
+ const parsed = parseFlightUrlParams(raw);
+
+ if (!parsed) {
+ return (
+
+
Invalid flight parameters.
+
+ );
+ }
+
+ return (
+ }>
+
+
+ );
+}
diff --git a/src/routes/[lang]/onlineboard/arrival/[params]/page.tsx b/src/routes/[lang]/onlineboard/arrival/[params]/page.tsx
new file mode 100644
index 00000000..b75d8950
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/arrival/[params]/page.tsx
@@ -0,0 +1,46 @@
+/**
+ * Online Board arrival search route.
+ *
+ * Parses station params from URL, renders shared search page.
+ * URL: /{lang}/onlineboard/arrival/{station}-{yyyyMMdd}[-{timeRange}]
+ */
+
+import { lazy, Suspense } from "react";
+import { useParams } from "@modern-js/runtime/router";
+import { parseStationUrlParams } from "@/features/online-board/url.js";
+import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
+
+const OnlineBoardSearchPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
+ (m) => ({ default: m.OnlineBoardSearchPage }),
+ ),
+);
+
+export default function ArrivalSearchPage(): JSX.Element {
+ const routeParams = useParams<{ params: string }>();
+ const raw = routeParams.params ?? "";
+ const parsed = parseStationUrlParams(raw);
+
+ if (!parsed) {
+ return (
+
+
Invalid arrival parameters.
+
+ );
+ }
+
+ const searchParams = {
+ type: "arrival" as const,
+ station: parsed.station,
+ date: parsed.date,
+ ...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
+ ? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
+ : {}),
+ };
+
+ return (
+ }>
+
+
+ );
+}
diff --git a/src/routes/[lang]/onlineboard/departure/[params]/page.tsx b/src/routes/[lang]/onlineboard/departure/[params]/page.tsx
new file mode 100644
index 00000000..6e68930f
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/departure/[params]/page.tsx
@@ -0,0 +1,46 @@
+/**
+ * Online Board departure search route.
+ *
+ * Parses station params from URL, renders shared search page.
+ * URL: /{lang}/onlineboard/departure/{station}-{yyyyMMdd}[-{timeRange}]
+ */
+
+import { lazy, Suspense } from "react";
+import { useParams } from "@modern-js/runtime/router";
+import { parseStationUrlParams } from "@/features/online-board/url.js";
+import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
+
+const OnlineBoardSearchPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
+ (m) => ({ default: m.OnlineBoardSearchPage }),
+ ),
+);
+
+export default function DepartureSearchPage(): JSX.Element {
+ const routeParams = useParams<{ params: string }>();
+ const raw = routeParams.params ?? "";
+ const parsed = parseStationUrlParams(raw);
+
+ if (!parsed) {
+ return (
+
+
Invalid departure parameters.
+
+ );
+ }
+
+ const searchParams = {
+ type: "departure" as const,
+ station: parsed.station,
+ date: parsed.date,
+ ...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
+ ? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
+ : {}),
+ };
+
+ return (
+ }>
+
+
+ );
+}
diff --git a/src/routes/[lang]/onlineboard/flight/[params]/page.tsx b/src/routes/[lang]/onlineboard/flight/[params]/page.tsx
new file mode 100644
index 00000000..7345e53b
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/flight/[params]/page.tsx
@@ -0,0 +1,45 @@
+/**
+ * Online Board flight number search route.
+ *
+ * Parses flight params from URL, renders shared search page.
+ * URL: /{lang}/onlineboard/flight/{carrier}{flightNumber}-{yyyyMMdd}
+ */
+
+import { lazy, Suspense } from "react";
+import { useParams } from "@modern-js/runtime/router";
+import { parseFlightUrlParams } from "@/features/online-board/url.js";
+import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
+
+const OnlineBoardSearchPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
+ (m) => ({ default: m.OnlineBoardSearchPage }),
+ ),
+);
+
+export default function FlightSearchPage(): JSX.Element {
+ const routeParams = useParams<{ params: string }>();
+ const raw = routeParams.params ?? "";
+ const parsed = parseFlightUrlParams(raw);
+
+ if (!parsed) {
+ return (
+
+
Invalid flight parameters.
+
+ );
+ }
+
+ return (
+ }>
+
+
+ );
+}
diff --git a/src/routes/[lang]/onlineboard/page.tsx b/src/routes/[lang]/onlineboard/page.tsx
new file mode 100644
index 00000000..04289e10
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/page.tsx
@@ -0,0 +1,22 @@
+/**
+ * Online Board start page route.
+ *
+ * Renders the search form landing page. No API calls on load.
+ * URL: /{lang}/onlineboard
+ */
+
+import { lazy, Suspense } from "react";
+
+const OnlineBoardStartPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardStartPage.js").then(
+ (m) => ({ default: m.OnlineBoardStartPage }),
+ ),
+);
+
+export default function OnlineBoardPage(): JSX.Element {
+ return (
+ Loading...}>
+
+
+ );
+}
diff --git a/src/routes/[lang]/onlineboard/route/[params]/page.tsx b/src/routes/[lang]/onlineboard/route/[params]/page.tsx
new file mode 100644
index 00000000..990d6437
--- /dev/null
+++ b/src/routes/[lang]/onlineboard/route/[params]/page.tsx
@@ -0,0 +1,47 @@
+/**
+ * Online Board route search page.
+ *
+ * Parses departure + arrival + date from URL, renders shared search page.
+ * URL: /{lang}/onlineboard/route/{dep}-{arr}-{yyyyMMdd}[-{timeRange}]
+ */
+
+import { lazy, Suspense } from "react";
+import { useParams } from "@modern-js/runtime/router";
+import { parseRouteUrlParams } from "@/features/online-board/url.js";
+import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
+
+const OnlineBoardSearchPage = lazy(() =>
+ import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
+ (m) => ({ default: m.OnlineBoardSearchPage }),
+ ),
+);
+
+export default function RouteSearchPage(): JSX.Element {
+ const routeParams = useParams<{ params: string }>();
+ const raw = routeParams.params ?? "";
+ const parsed = parseRouteUrlParams(raw);
+
+ if (!parsed) {
+ return (
+
+
Invalid route parameters.
+
+ );
+ }
+
+ const searchParams = {
+ type: "route" as const,
+ departure: parsed.departure,
+ arrival: parsed.arrival,
+ date: parsed.date,
+ ...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
+ ? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
+ : {}),
+ };
+
+ return (
+ }>
+
+
+ );
+}