diff --git a/web/src/App.tsx b/web/src/App.tsx
new file mode 100644
index 0000000..a26ad2c
--- /dev/null
+++ b/web/src/App.tsx
@@ -0,0 +1,196 @@
+import { useEffect, useMemo, useState } from "react";
+import { AnimatePresence, LayoutGroup, motion } from "motion/react";
+import { useMonitor } from "./hooks/useMonitor";
+import { springs, UIProvider, useUI } from "./lib/ui";
+import type { CheckKind } from "./lib/types";
+import { fmtNumber } from "./lib/format";
+import { Header } from "./components/Header";
+import { Boot } from "./components/Boot";
+import { TargetCard } from "./components/TargetCard";
+import { TargetDetail } from "./components/TargetDetail";
+import { OrbitalOverview } from "./components/OrbitalOverview";
+import { RadialDay } from "./components/RadialDay";
+import { IncidentList } from "./components/IncidentList";
+import { PublicView } from "./components/PublicView";
+
+const MIN_BOOT_MS = 1700;
+
+type Filter = "all" | CheckKind;
+
+function FilterChips({
+ targets,
+ filter,
+ onChange,
+}: {
+ targets: { type: CheckKind }[];
+ filter: Filter;
+ onChange: (f: Filter) => void;
+}) {
+ const { t, lang, reduced } = useUI();
+ const kinds = useMemo(() => {
+ const present = new Set(targets.map((x) => x.type));
+ return (["http", "tls", "tcp", "icmp", "docker"] as CheckKind[]).filter((k) =>
+ present.has(k),
+ );
+ }, [targets]);
+
+ if (kinds.length < 2) return null;
+
+ const chip = (value: Filter, label: string, count: number) => {
+ const active = filter === value;
+ return (
+
+ );
+ };
+
+ return (
+
+ {chip("all", t.all, targets.length)}
+ {kinds.map((k) =>
+ chip(k, k, targets.filter((x) => x.type === k).length),
+ )}
+
+ );
+}
+
+function Shell() {
+ const monitor = useMonitor();
+ const { t, mode, reduced } = useUI();
+ const [selected, setSelected] = useState(
+ () => decodeURIComponent(location.hash.slice(1)) || null,
+ );
+ const [filter, setFilter] = useState("all");
+ const [bootElapsed, setBootElapsed] = useState(reduced);
+
+ useEffect(() => {
+ const id = setTimeout(() => setBootElapsed(true), reduced ? 0 : MIN_BOOT_MS);
+ return () => clearTimeout(id);
+ }, [reduced]);
+
+ const booted = monitor.ready && bootElapsed;
+ const selectedTarget = monitor.targets.find((x) => x.id === selected) ?? null;
+
+ // The selected target lives in the URL — deep-linkable, back-button friendly.
+ const select = (id: string | null) => {
+ setSelected(id);
+ history.replaceState(null, "", id ? `#${encodeURIComponent(id)}` : location.pathname);
+ };
+
+ useEffect(() => {
+ const onKey = (e: KeyboardEvent) => {
+ if (e.key === "Escape") select(null);
+ };
+ window.addEventListener("keydown", onKey);
+ return () => window.removeEventListener("keydown", onKey);
+ }, []);
+
+ const visibleTargets =
+ filter === "all"
+ ? monitor.targets
+ : monitor.targets.filter((x) => x.type === filter);
+
+ return (
+
+
{!booted && }
+
+ {booted && (
+ <>
+
+
+
+ {mode === "public" ? (
+
+ ) : (
+
+
+ {/* hero: orbit + day dial */}
+
+
+ {/* targets grid */}
+
+
+
+
+ {visibleTargets.map((target, i) => (
+
+ ))}
+
+
+
+
+
+
+ {selectedTarget && (
+ i.target_id === selectedTarget.id,
+ )}
+ onClose={() => select(null)}
+ />
+ )}
+
+
+ )}
+ >
+ )}
+
+ );
+}
+
+export default function App() {
+ return (
+
+
+
+ );
+}