)}
diff --git a/frontend/src/components/NavSidebar.tsx b/frontend/src/components/NavSidebar.tsx
index 56a635b..965d6be 100644
--- a/frontend/src/components/NavSidebar.tsx
+++ b/frontend/src/components/NavSidebar.tsx
@@ -256,8 +256,9 @@ export default function NavSidebar({
{!collapsed && (
diff --git a/frontend/src/components/PageTitle.tsx b/frontend/src/components/PageTitle.tsx
new file mode 100644
index 0000000..1ea61ae
--- /dev/null
+++ b/frontend/src/components/PageTitle.tsx
@@ -0,0 +1,11 @@
+// The centered module title in the top bar. Every non-feed module renders through this one
+// component, so its styling lives in a single place. Design element (user-picked): a tracked
+// small-caps "eyebrow" with a leading accent dot.
+export default function PageTitle({ label }: { label: string }) {
+ return (
+
+
+ {label}
+
+ );
+}
diff --git a/frontend/src/lib/pageMeta.ts b/frontend/src/lib/pageMeta.ts
new file mode 100644
index 0000000..19dd9d9
--- /dev/null
+++ b/frontend/src/lib/pageMeta.ts
@@ -0,0 +1,32 @@
+import type { Page } from "./urlState";
+
+// The i18n key for a page's human title — shared by the top-bar header and the browser tab title
+// so the two never drift. Keep in sync with the nav modules in NavSidebar / App's page switch.
+export function pageTitleKey(page: Page): string {
+ switch (page) {
+ case "feed":
+ return "header.account.feed";
+ case "channels":
+ return "header.channelManager";
+ case "playlists":
+ return "header.account.playlists";
+ case "notifications":
+ return "inbox.navLabel";
+ case "messages":
+ return "messages.navLabel";
+ case "downloads":
+ return "downloads.navLabel";
+ case "stats":
+ return "header.usageStats";
+ case "scheduler":
+ return "header.scheduler";
+ case "config":
+ return "header.configuration";
+ case "users":
+ return "header.users";
+ case "settings":
+ return "settings.title";
+ default:
+ return "header.account.feed";
+ }
+}