From aa875e36adb095818366d0ed1df778ee330e5c2a Mon Sep 17 00:00:00 2001
From: Jared Pereira
Date: Thu, 07 May 2026 21:43:08 +0000
Subject: [PATCH] Refactor/route nav (#294)
* move tabs into sidebar
* move dashboard pages into new layout, tweak mobile layout
* renaming and componentizing things in the Dashboard Layouts for clarity
* componentize the search input on pages
* added sidebar on mobile, refactored some stuff
* added sticky scroll behavior to mobile header
* animations for the mobile pageHeader
* fix mobile nav trigger and component structure
* futzing
* more futzing
* Added logged out state to Reader Inbox, refactored reader to use new
layout
* fix a z-index issue
* use route based navigation
* remove logs and small fixes
* simplify
* small fixes
* updates to leaflet to accomodate sidebar changes
* dynamic notification page
* fix search when signed out
* prevent default and add stop propogration to email submit
* added new tab to the reader, decodeds urls in pickActiveTab function
* tweaks to publish banner in sidebar to avoid redundancy
* bubble up notifactions, scroll very long pub lists
* rm interaction drawer in reader, add a layout component to reader pages
* added leaflet about
* move mobile nav to the bottom
* added icons to the tabs
* handle signed out users side bar actions
---------
Co-authored-by: celine
---
CLAUDE.md | 2 +-
app/globals.css | 37 +++++++++++++++++++++++++++++++++++++
components/IdentityProvider.tsx | 2 +-
components/LoginButton.tsx | 24 +++++++++++++++++++-----
components/Media.tsx | 4 +++-
components/Modal.tsx | 32 +++++++++++++++++++++++++-------
components/PageHeader.tsx | 8 +++++---
components/PostListing.tsx | 9 +++++----
components/SpeedyLink.tsx | 2 ++
components/ToggleGroup.tsx | 6 +++++-
components/ViewportSizeLayout.tsx | 122 ++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------
app/(home-pages)/page.tsx | 26 +++++---------------------
app/[leaflet_id]/Footer.tsx | 27 +++++++++++++++++++++++----
app/[leaflet_id]/Leaflet.tsx | 2 --
app/[leaflet_id]/Sidebar.tsx | 25 ++++++++++++++++++++++---
components/ActionBar/ActionButton.tsx | 40 ++++++++++++++++++++++------------------
components/ActionBar/DesktopNavigation.tsx | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------
components/ActionBar/MobileNavigation.tsx | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------
components/ActionBar/NavigationButtons.tsx | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------
components/ActionBar/ProfileButton.tsx | 6 +++---
components/ActionBar/PublicationNavigation.tsx | 148 ----------------------------------------------------------------------------------------------------------------------------------------------------
components/ActionBar/Publications.tsx | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------------------------------------------------
components/ActionBar/Sidebar.tsx | 33 +++++++++++++++++++++++++++------
components/Icons/AnalyticsSmall.tsx | 19 +++++++++++++++++++
components/Icons/GoToArrowLined.tsx | 22 ++++++++++++++++++++++
components/Icons/LeafletTiny.tsx | 19 +++++++++++++++++++
components/Icons/MenuSmall.tsx | 1 +
components/Icons/NewSmall.tsx | 19 +++++++++++++++++++
components/Icons/SortSmall.tsx | 1 +
components/Icons/SubscribersSmall.tsx | 21 +++++++++++++++++++++
components/Icons/TrendingSmall.tsx | 19 +++++++++++++++++++
components/PageLayouts/DashboardLayout.tsx | 580 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
components/PageLayouts/DashboardPageLayout.tsx | 39 +++++++++++++++++++++++++++++++++++++++
components/PageLayouts/DashboardShell.tsx | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
components/PageLayouts/NotificationContent.tsx | 32 ++++++++++++++++++++++++++++++++
components/PageLayouts/PageSearch.tsx | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
components/PageLayouts/dashboardState.ts | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
components/Popover/index.tsx | 11 +++++++++--
components/Subscribe/HandleSubscribe.tsx | 6 +++---
components/ThemeManager/ThemeSetter.tsx | 26 +++++++++-----------------
components/utils/AddLeafletToHomepage.tsx | 20 --------------------
components/utils/DotLoader.tsx | 1 +
src/hooks/isMobile.ts | 1 +
app/(home-pages)/(writer)/WriterShell.tsx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/layout.tsx | 5 +++++
app/(home-pages)/home/HomeLayout.tsx | 309 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
app/(home-pages)/home/IdentitySetter.tsx | 13 -------------
app/(home-pages)/home/icon.tsx | 105 ---------------------------------------------------------------------------------------------------------
app/(home-pages)/home/page.tsx | 44 --------------------------------------------
app/(home-pages)/home/storage.ts | 68 --------------------------------------------------------------------
app/(home-pages)/looseleafs/LooseleafsLayout.tsx | 111 ---------------------------------------------------------------------------------------------------------------
app/(home-pages)/looseleafs/page.tsx | 47 -----------------------------------------------
app/(home-pages)/notifications/BskyPostEmbedNotification.tsx | 41 -----------------------------------------
app/(home-pages)/notifications/CommentMentionNotification.tsx | 89 -----------------------------------------------------------------------------------------
app/(home-pages)/notifications/CommentNotication.tsx | 59 -----------------------------------------------------------
app/(home-pages)/notifications/FollowNotification.tsx | 34 ----------------------------------
app/(home-pages)/notifications/MentionNotification.tsx | 62 --------------------------------------------------------------
app/(home-pages)/notifications/Notification.tsx | 112 ----------------------------------------------------------------------------------------------------------------
app/(home-pages)/notifications/NotificationList.tsx | 71 -----------------------------------------------------------------------
app/(home-pages)/notifications/QuoteNotification.tsx | 42 ------------------------------------------
app/(home-pages)/notifications/RecommendNotification.tsx | 45 ---------------------------------------------
app/(home-pages)/notifications/ReplyNotification.tsx | 83 -----------------------------------------------------------------------------------
app/(home-pages)/notifications/getNotifications.ts | 28 ----------------------------
app/(home-pages)/notifications/page.tsx | 35 -----------------------------------
app/(home-pages)/reader/FeedLayout.tsx | 7 +++++++
app/(home-pages)/reader/GlobalContent.tsx | 26 +++++++++-----------------
app/(home-pages)/reader/InboxContent.tsx | 67 +++++++++++++++++++++++++++++++++++--------------------------------
app/(home-pages)/reader/InteractionDrawers.tsx | 117 ---------------------------------------------------------------------------------------------------------------------
app/(home-pages)/reader/NewContent.tsx | 44 ++++++++++++++++++--------------------------
app/(home-pages)/reader/layout.tsx | 88 +++++++++++++++++++++-------------------------------------------------------------------
app/(home-pages)/reader/loading.tsx | 4 ----
app/(home-pages)/reader/page.tsx | 36 ++++++++++++++++++++++++++----------
app/[leaflet_id]/actions/HomeButton.tsx | 55 +++++++++++++++++++++++++++++--------------------------
app/[leaflet_id]/actions/PublishButton.tsx | 8 +++++++-
app/[leaflet_id]/publish/PublishPost.tsx | 2 +-
app/(home-pages)/(writer)/home/HomeLayout.tsx | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/IdentitySetter.tsx | 13 +++++++++++++
app/(home-pages)/(writer)/home/icon.tsx | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/page.tsx | 44 ++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/storage.ts | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/looseleafs/LooseleafsLayout.tsx | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/looseleafs/page.tsx | 43 +++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/BskyPostEmbedNotification.tsx | 41 +++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/CommentMentionNotification.tsx | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/CommentNotication.tsx | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/FollowNotification.tsx | 34 ++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/MentionNotification.tsx | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/Notification.tsx | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/NotificationList.tsx | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/QuoteNotification.tsx | 42 ++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/RecommendNotification.tsx | 45 +++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/ReplyNotification.tsx | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/getNotifications.ts | 28 ++++++++++++++++++++++++++++
app/(home-pages)/(writer)/notifications/page.tsx | 29 +++++++++++++++++++++++++++++
app/(home-pages)/home/Actions/AccountSettings.tsx | 24 ------------------------
app/(home-pages)/home/Actions/Actions.tsx | 18 ------------------
app/(home-pages)/home/Actions/CreateNewButton.tsx | 71 -----------------------------------------------------------------------
app/(home-pages)/home/Actions/HomeHelp.tsx | 27 ---------------------------
app/(home-pages)/home/HomeEmpty/DiscoverIllo.tsx | 26 --------------------------
app/(home-pages)/home/HomeEmpty/HomeEmpty.tsx | 84 ------------------------------------------------------------------------------------
app/(home-pages)/home/HomeEmpty/WelcomeToLeafletIllo.tsx | 24 ------------------------
app/(home-pages)/home/LeafletList/LeafletContent.tsx | 68 --------------------------------------------------------------------
app/(home-pages)/home/LeafletList/LeafletInfo.tsx | 60 ------------------------------------------------------------
app/(home-pages)/home/LeafletList/LeafletListItem.tsx | 113 -----------------------------------------------------------------------------------------------------------------
app/(home-pages)/home/LeafletList/LeafletOptions.tsx | 351 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
app/(home-pages)/home/LeafletList/LeafletPreview.module.css | 16 ----------------
app/(home-pages)/home/LeafletList/LeafletPreview.tsx | 138 ------------------------------------------------------------------------------------------------------------------------------------------
app/(home-pages)/p/[didOrHandle]/layout.tsx | 44 ++++++++++++++++++++++++--------------------
app/(home-pages)/reader/hot/page.tsx | 8 +++-----
app/(home-pages)/reader/new/page.tsx | 21 ++++++++++++++++++---
app/(home-pages)/reader/trending/page.tsx | 22 ++++++++++++++++++++++
app/(home-pages)/tag/[tag]/layout.tsx | 24 ++++++++++++++++++++++++
app/(home-pages)/tag/[tag]/page.tsx | 21 ++++++++-------------
app/[leaflet_id]/actions/ShareOptions/index.tsx | 2 ++
app/lish/[did]/[publication]/UpgradeModal.tsx | 1 +
app/(home-pages)/(writer)/home/Actions/Actions.tsx | 16 ++++++++++++++++
app/(home-pages)/(writer)/home/Actions/CreateNewButton.tsx | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/Actions/HomeThemeSetter.tsx | 30 ++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/HomeEmpty/DiscoverIllo.tsx | 26 ++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/HomeEmpty/HomeEmpty.tsx | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/HomeEmpty/WelcomeToLeafletIllo.tsx | 24 ++++++++++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletContent.tsx | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletInfo.tsx | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletListItem.tsx | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletOptions.tsx | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletPreview.module.css | 16 ++++++++++++++++
app/(home-pages)/(writer)/home/LeafletList/LeafletPreview.tsx | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/Actions.tsx | 9 ++-------
app/lish/[did]/[publication]/dashboard/DraftList.tsx | 2 +-
app/lish/[did]/[publication]/dashboard/DraftsTab.tsx | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/NewDraftButton.tsx | 27 +++++++++++++++++++--------
app/lish/[did]/[publication]/dashboard/PublicationDashboard.tsx | 109 -------------------------------------------------------------------------------------------------------------
app/lish/[did]/[publication]/dashboard/PublicationSubscribers.tsx | 2 +-
app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx | 4 ++--
app/lish/[did]/[publication]/dashboard/layout.tsx | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/page.tsx | 109 ++++++++++++++-----------------------------------------------------------------------------------------------
app/lish/[did]/[publication]/theme-settings/ThemeSettingsContent.tsx | 2 +-
app/lish/[did]/[publication]/dashboard/analytics/page.tsx | 39 +++++++++++++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/posts/page.tsx | 42 ++++++++++++++++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/settings/ProSettings.tsx | 10 +++++++---
app/lish/[did]/[publication]/dashboard/settings/page.tsx | 28 ++++++++++++++++++++++++++++
app/lish/[did]/[publication]/dashboard/subs/page.tsx | 32 ++++++++++++++++++++++++++++++++
142 file(s) changed, 4563 insertion(s)(+), 4173 deletion(s)(-)
diff --git a/CLAUDE.md b/CLAUDE.md
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -71,4 +71,4 @@
- **React contexts**: `DocumentProvider`, `LeafletContentProvider` for page-level data
- **Inngest functions**: Async jobs in `app/api/inngest/functions/`
- **Icons**: Icon components live in `components/Icons/`. Each icon is a named export in its own file (e.g. `RefreshSmall.tsx`), imports `Props` from `./Props`, spreads `{...props}` on the `
-
- If the issue persists please{" "}
- send us a note.
-
-
- );
- let did = decodeURIComponent(params.did);
- if (!did) return ;
- let { result: publication_data } = await get_publication_data.handler(
- {
- did,
- publication_name: decodeURIComponent((await props.params).publication),
- },
- { supabase: supabaseServerClient },
- );
- let { publication, leaflet_data } = publication_data;
- const record = normalizePublicationRecord(publication?.record);
-
- if (!publication || identity.atp_did !== publication.identity_did || !record)
- return ;
- let uri = new AtUri(publication.uri);
-
- try {
- return (
-
-
-
-
-
- );
- } catch (e) {
- return {JSON.stringify(e, undefined, 2)};
+ const { tab } = await props.searchParams;
+ if (tab && tab !== "Drafts") {
+ const params = await props.params;
+ const base = `/lish/${params.did}/${params.publication}/dashboard`;
+ if (tab === "Posts") redirect(`${base}/posts`);
+ if (tab === "Subs") redirect(`${base}/subs`);
+ if (tab === "Analytics") redirect(`${base}/analytics`);
+ if (tab === "Settings") redirect(`${base}/settings`);
}
-}
-const PubNotFound = () => {
- return (
-
- Sorry, we can't find this publication!
-
- This may be a glitch on our end. If the issue persists please{" "}
- send us a note.
-
-
- );
-};
+ return ;
+}
diff --git a/app/lish/[did]/[publication]/theme-settings/ThemeSettingsContent.tsx b/app/lish/[did]/[publication]/theme-settings/ThemeSettingsContent.tsx
--- a/app/lish/[did]/[publication]/theme-settings/ThemeSettingsContent.tsx
+++ b/app/lish/[did]/[publication]/theme-settings/ThemeSettingsContent.tsx
@@ -46,7 +46,7 @@
changes,
} = state;
- let settingsHref = `/lish/${params.did}/${params.publication}/dashboard?tab=Settings`;
+ let settingsHref = `/lish/${params.did}/${params.publication}/dashboard/settings`;
let hasUnsavedChanges =
changes ||
diff --git a/app/lish/[did]/[publication]/dashboard/analytics/page.tsx b/app/lish/[did]/[publication]/dashboard/analytics/page.tsx
new file mode 100644
--- /dev/null
+++ b/app/lish/[did]/[publication]/dashboard/analytics/page.tsx
@@ -0,0 +1,39 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { useEffect } from "react";
+import { DashboardPageLayout } from "components/PageLayouts/DashboardPageLayout";
+import { PublicationAnalytics } from "../PublicationAnalytics";
+import { NewDraftActionButton } from "../NewDraftButton";
+import {
+ usePublicationData,
+ useNormalizedPublicationRecord,
+} from "../PublicationSWRProvider";
+import { useCanSeePro } from "src/hooks/useEntitlement";
+
+export default function AnalyticsPage() {
+ let canSeePro = useCanSeePro();
+ let router = useRouter();
+ let { data } = usePublicationData();
+ let record = useNormalizedPublicationRecord();
+ let pubUri = data?.publication?.uri || "";
+ const showPageBackground = !!record?.theme?.showPageBackground;
+
+ useEffect(() => {
+ if (canSeePro === false) router.replace("../");
+ }, [canSeePro, router]);
+
+ if (!canSeePro) return null;
+
+ return (
+ }
+ publication={pubUri}
+ showHeader={false}
+ >
+
+
+ );
+}
diff --git a/app/lish/[did]/[publication]/dashboard/posts/page.tsx b/app/lish/[did]/[publication]/dashboard/posts/page.tsx
new file mode 100644
--- /dev/null
+++ b/app/lish/[did]/[publication]/dashboard/posts/page.tsx
@@ -0,0 +1,42 @@
+"use client";
+
+import { useState } from "react";
+import { useDebouncedEffect } from "src/hooks/useDebouncedEffect";
+import { DashboardPageLayout } from "components/PageLayouts/DashboardPageLayout";
+import { PublishedPostsList } from "../PublishedPostsLists";
+import { NewDraftActionButton } from "../NewDraftButton";
+import {
+ usePublicationData,
+ useNormalizedPublicationRecord,
+} from "../PublicationSWRProvider";
+
+export default function PostsPage() {
+ let { data } = usePublicationData();
+ let record = useNormalizedPublicationRecord();
+ let pubUri = data?.publication?.uri || "";
+
+ let [searchValue, setSearchValue] = useState("");
+ let [debouncedSearchValue, setDebouncedSearchValue] = useState("");
+ useDebouncedEffect(
+ () => setDebouncedSearchValue(searchValue),
+ 200,
+ [searchValue],
+ );
+
+ const showPageBackground = !!record?.theme?.showPageBackground;
+
+ return (
+ }
+ publication={pubUri}
+ showHeader={false}
+ >
+
+
+ );
+}
diff --git a/app/lish/[did]/[publication]/dashboard/settings/ProSettings.tsx b/app/lish/[did]/[publication]/dashboard/settings/ProSettings.tsx
--- a/app/lish/[did]/[publication]/dashboard/settings/ProSettings.tsx
+++ b/app/lish/[did]/[publication]/dashboard/settings/ProSettings.tsx
@@ -1,3 +1,4 @@
+"use client";
import { useEffect, useMemo, useState } from "react";
import { ButtonPrimary, ButtonSecondary } from "components/Buttons";
import { createBillingPortalSession } from "actions/createBillingPortalSession";
@@ -171,13 +172,16 @@
-