diff --git a/web/src/app/utils.js b/web/src/app/utils.js
index c9b5b4c5..d8763409 100644
--- a/web/src/app/utils.js
+++ b/web/src/app/utils.js
@@ -10,6 +10,7 @@ export const topicUrlJsonPollWithSince = (baseUrl, topic, since) => `${topicUrlJ
 export const topicUrlAuth = (baseUrl, topic) => `${topicUrl(baseUrl, topic)}/auth`;
 export const topicShortUrl = (baseUrl, topic) => shortUrl(topicUrl(baseUrl, topic));
 export const shortUrl = (url) => url.replaceAll(/https?:\/\//g, "");
+export const expandUrl = (url) => [`https://${url}`, `http://${url}`];
 
 export const validUrl = (url) => {
     return url.match(/^https?:\/\//);
diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js
index 88e36dcd..a135a238 100644
--- a/web/src/components/ActionBar.js
+++ b/web/src/components/ActionBar.js
@@ -22,8 +22,8 @@ import subscriptionManager from "../app/SubscriptionManager";
 const ActionBar = (props) => {
     const location = useLocation();
     let title = "ntfy";
-    if (props.selectedSubscription) {
-        title = topicShortUrl(props.selectedSubscription.baseUrl, props.selectedSubscription.topic);
+    if (props.selected) {
+        title = topicShortUrl(props.selected.baseUrl, props.selected.topic);
     } else if (location.pathname === "/settings") {
         title = "Settings";
     }
@@ -50,8 +50,8 @@ const ActionBar = (props) => {
                 <Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
                     {title}
                 </Typography>
-                {props.selectedSubscription && <SettingsIcon
-                    subscription={props.selectedSubscription}
+                {props.selected && <SettingsIcon
+                    subscription={props.selected}
                     onUnsubscribe={props.onUnsubscribe}
                 />}
             </Toolbar>
diff --git a/web/src/components/App.js b/web/src/components/App.js
index 2367fa6b..29899850 100644
--- a/web/src/components/App.js
+++ b/web/src/components/App.js
@@ -12,16 +12,12 @@ import ActionBar from "./ActionBar";
 import notifier from "../app/Notifier";
 import Preferences from "./Preferences";
 import {useLiveQuery} from "dexie-react-hooks";
-import poller from "../app/Poller";
-import pruner from "../app/Pruner";
 import subscriptionManager from "../app/SubscriptionManager";
 import userManager from "../app/UserManager";
-import {BrowserRouter, Route, Routes, useLocation, useNavigate} from "react-router-dom";
-import {subscriptionRoute} from "../app/utils";
+import {BrowserRouter, Route, Routes, useNavigate, useParams} from "react-router-dom";
+import {expandUrl, subscriptionRoute} from "../app/utils";
 
 // TODO support unsubscribed routes
-// TODO add "home" route that is selected when nothing else fits
-// TODO new notification indicator
 // TODO "copy url" toast
 // TODO "copy link url" button
 // TODO races when two tabs are open
@@ -32,42 +28,78 @@ const App = () => {
         <BrowserRouter>
             <ThemeProvider theme={theme}>
                 <CssBaseline/>
-                <Root/>
+                <Content/>
             </ThemeProvider>
         </BrowserRouter>
     );
 }
 
-const Root = () => {
+const Content = () => {
+    const subscriptions = useLiveQuery(() => subscriptionManager.all());
+    // const context = { subscriptions };
+    return (
+        <Routes>
+            <Route path="settings" element={<PrefLayout subscriptions={subscriptions}/>} />
+            <Route path="settings" element={<PrefLayout subscriptions={subscriptions}/>} />
+            <Route path="/" element={<AllSubscriptions subscriptions={subscriptions}/>} />
+            <Route path=":baseUrl/:topic" element={<SingleSubscription subscriptions={subscriptions}/>} />
+            <Route path=":topic" element={<SingleSubscription subscriptions={subscriptions}/>} />
+        </Routes>
+    )
+};
+
+const AllSubscriptions = (props) => {
+    return (
+        <Layout subscriptions={props.subscriptions}>
+            <Notifications mode="all" subscriptions={props.subscriptions}/>
+        </Layout>
+    );
+}
+
+const SingleSubscription = (props) => {
+    const params = useParams();
+    const [selected] = (props.subscriptions || []).filter(s => {
+        return (params.baseUrl && expandUrl(params.baseUrl).includes(s.baseUrl) && params.topic === s.topic)
+            || (window.location.origin === s.baseUrl && params.topic === s.topic)
+    });
+    return (
+        <Layout subscriptions={props.subscriptions} selected={selected}>
+            <Notifications mode="one" subscription={selected}/>
+        </Layout>
+    );
+}
+
+const PrefLayout = (props) => {
+    return (
+        <Layout subscriptions={props.subscriptions}>
+            <Preferences/>
+        </Layout>
+    );
+}
+
+const Layout = (props) => {
+    const subscriptions = props.subscriptions; // May be null/undefined
+    const selected = props.selected; // May be null/undefined
     const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false);
     const [notificationsGranted, setNotificationsGranted] = useState(notifier.granted());
-    const location = useLocation();
     const users = useLiveQuery(() => userManager.all());
-    const subscriptions = useLiveQuery(() => subscriptionManager.all());
-    const selectedSubscription = findSelected(location, subscriptions);
     const newNotificationsCount = subscriptions?.reduce((prev, cur) => prev + cur.new, 0) || 0;
 
     useConnectionListeners();
 
-    useEffect(() => {
-        connectionManager.refresh(subscriptions, users);
-    }, [subscriptions, users]); // Dangle!
-
-    useEffect(() => {
-        document.title = (newNotificationsCount > 0) ? `(${newNotificationsCount}) ntfy web` : "ntfy web";
-    }, [newNotificationsCount]);
+    useEffect(() => connectionManager.refresh(subscriptions, users), [subscriptions, users]);
+    useEffect(() => updateTitle(newNotificationsCount), [newNotificationsCount]);
 
     return (
         <Box sx={{display: 'flex'}}>
             <CssBaseline/>
             <ActionBar
-                subscriptions={subscriptions}
-                selectedSubscription={selectedSubscription}
+                selected={selected}
                 onMobileDrawerToggle={() => setMobileDrawerOpen(!mobileDrawerOpen)}
             />
             <Navigation
                 subscriptions={subscriptions}
-                selectedSubscription={selectedSubscription}
+                selectedSubscription={selected}
                 notificationsGranted={notificationsGranted}
                 mobileDrawerOpen={mobileDrawerOpen}
                 onMobileDrawerToggle={() => setMobileDrawerOpen(!mobileDrawerOpen)}
@@ -75,12 +107,7 @@ const Root = () => {
             />
             <Main>
                 <Toolbar/>
-                <Routes>
-                    <Route path="settings" element={<Preferences />} />
-                    <Route path="/" element={<Notifications mode="all" subscriptions={subscriptions} />} />
-                    <Route path=":baseUrl/:topic" element={<Notifications mode="one" subscription={selectedSubscription}/>} />
-                    <Route path=":topic" element={<Notifications mode="one" subscription={selectedSubscription}/>} />
-                </Routes>
+                {props.children}
             </Main>
         </Box>
     );
@@ -107,32 +134,6 @@ const Main = (props) => {
     );
 };
 
-const findSelected = (location, subscriptions) => {
-    if (!subscriptions || !location)  {
-        return null;
-    }
-    const [subscription] = subscriptions.filter(s => location.pathname === subscriptionRoute(s));
-    return subscription;
-
-    /*
-    if (location.pathname === "/" || location.pathname === "/settings") {
-        return null;
-    }
-    if (!subscription) {
-        const [, topic] = location.pathname.split("/");
-        const subscription = {
-            id: topicUrl(window.location.origin, topic),
-            baseUrl: window.location.origin,
-            topic: topic,
-            last: ""
-        }
-        subscriptionManager.save(subscription);
-        return subscription;
-    }
-
-     */
-};
-
 const useConnectionListeners = () => {
     const navigate = useNavigate();
     useEffect(() => {
@@ -155,4 +156,8 @@ const useConnectionListeners = () => {
     []);
 };
 
+const updateTitle = (newNotificationsCount) => {
+    document.title = (newNotificationsCount > 0) ? `(${newNotificationsCount}) ntfy web` : "ntfy web";
+}
+
 export default App;