diff --git a/src/components/layout/app-shell.tsx b/src/components/layout/app-shell.tsx
new file mode 100644
index 0000000..b18f0f4
--- /dev/null
+++ b/src/components/layout/app-shell.tsx
@@ -0,0 +1,18 @@
+import type { ReactNode } from "react";
+import { useLocation } from "react-router";
+import { Sidebar } from "./sidebar";
+
+interface AppShellProps {
+ children: ReactNode;
+}
+
+export const AppShell = ({ children }: AppShellProps) => {
+ const { pathname } = useLocation();
+
+ return (
+
+
+ {children}
+
+ );
+};
diff --git a/src/components/layout/sidebar.tsx b/src/components/layout/sidebar.tsx
new file mode 100644
index 0000000..a8cd367
--- /dev/null
+++ b/src/components/layout/sidebar.tsx
@@ -0,0 +1,126 @@
+import type { FC, HTMLAttributes } from "react";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+ faBullhorn,
+ faChartMixed,
+ faCommentDots,
+ faGear,
+ faGrid2,
+ faPlug,
+} from "@fortawesome/pro-regular-svg-icons";
+import { MobileNavigationHeader } from "@/components/application/app-navigation/base-components/mobile-header";
+import { NavAccountCard } from "@/components/application/app-navigation/base-components/nav-account-card";
+import { NavItemBase } from "@/components/application/app-navigation/base-components/nav-item";
+import type { NavItemType } from "@/components/application/app-navigation/config";
+
+// TODO: Wire to useAuth() once auth-provider.tsx is implemented
+const isAdmin = false;
+
+const MAIN_SIDEBAR_WIDTH = 292;
+
+// FontAwesome icon wrappers that satisfy FC>
+const IconGrid2: FC> = ({ className }) => (
+
+);
+const IconBullhorn: FC> = ({ className }) => (
+
+);
+const IconCommentDots: FC> = ({ className }) => (
+
+);
+const IconChartMixed: FC> = ({ className }) => (
+
+);
+const IconPlug: FC> = ({ className }) => (
+
+);
+const IconGear: FC> = ({ className }) => (
+
+);
+
+const mainItems: NavItemType[] = [
+ { label: "Lead Workspace", href: "/", icon: IconGrid2 },
+ { label: "Campaigns", href: "/campaigns", icon: IconBullhorn },
+ { label: "Outreach", href: "/outreach", icon: IconCommentDots },
+];
+
+const insightsItems: NavItemType[] = [
+ { label: "Analytics", href: "/analytics", icon: IconChartMixed },
+];
+
+const adminItems: NavItemType[] = [
+ { label: "Integrations", href: "/integrations", icon: IconPlug },
+ { label: "Settings", href: "/settings", icon: IconGear },
+];
+
+interface SidebarProps {
+ activeUrl?: string;
+}
+
+export const Sidebar = ({ activeUrl = "/" }: SidebarProps) => {
+ const navSections = [
+ { label: "Main", items: mainItems },
+ { label: "Insights", items: insightsItems },
+ ...(isAdmin ? [{ label: "Admin", items: adminItems }] : []),
+ ];
+
+ const content = (
+
+ );
+
+ return (
+ <>
+ {/* Mobile header navigation */}
+ {content}
+
+ {/* Desktop sidebar navigation */}
+ {content}
+
+ {/* Placeholder to take up physical space because the real sidebar has `fixed` position. */}
+
+ >
+ );
+};
diff --git a/src/components/layout/top-bar.tsx b/src/components/layout/top-bar.tsx
new file mode 100644
index 0000000..c833e36
--- /dev/null
+++ b/src/components/layout/top-bar.tsx
@@ -0,0 +1,30 @@
+import { SearchLg } from "@untitledui/icons";
+import { Avatar } from "@/components/base/avatar/avatar";
+import { Input } from "@/components/base/input/input";
+
+interface TopBarProps {
+ title: string;
+ subtitle?: string;
+}
+
+export const TopBar = ({ title, subtitle }: TopBarProps) => {
+ return (
+
+
+
{title}
+ {subtitle &&
{subtitle}
}
+
+
+
+
+ );
+};
diff --git a/src/main.tsx b/src/main.tsx
index 947dae7..7cf1b00 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,8 +1,14 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
-import { BrowserRouter, Route, Routes } from "react-router";
-import { HomeScreen } from "@/pages/home-screen";
+import { BrowserRouter, Outlet, Route, Routes } from "react-router";
+import { AppShell } from "@/components/layout/app-shell";
import { NotFound } from "@/pages/not-found";
+import { AllLeadsPage } from "@/pages/all-leads";
+import { CampaignDetailPage } from "@/pages/campaign-detail";
+import { CampaignsPage } from "@/pages/campaigns";
+import { LeadWorkspacePage } from "@/pages/lead-workspace";
+import { LoginPage } from "@/pages/login";
+import { OutreachPage } from "@/pages/outreach";
import { RouteProvider } from "@/providers/router-provider";
import { ThemeProvider } from "@/providers/theme-provider";
import "@/styles/globals.css";
@@ -13,8 +19,21 @@ createRoot(document.getElementById("root")!).render(
- } />
- } />
+ } />
+
+
+
+ }
+ >
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
diff --git a/src/pages/all-leads.tsx b/src/pages/all-leads.tsx
new file mode 100644
index 0000000..018d4f0
--- /dev/null
+++ b/src/pages/all-leads.tsx
@@ -0,0 +1,12 @@
+import { TopBar } from "@/components/layout/top-bar";
+
+export const AllLeadsPage = () => {
+ return (
+
+
+
+
All Leads — coming soon
+
+
+ );
+};
diff --git a/src/pages/campaign-detail.tsx b/src/pages/campaign-detail.tsx
new file mode 100644
index 0000000..f27804b
--- /dev/null
+++ b/src/pages/campaign-detail.tsx
@@ -0,0 +1,12 @@
+import { TopBar } from "@/components/layout/top-bar";
+
+export const CampaignDetailPage = () => {
+ return (
+
+
+
+
Campaign Detail — coming soon
+
+
+ );
+};
diff --git a/src/pages/campaigns.tsx b/src/pages/campaigns.tsx
new file mode 100644
index 0000000..25c713f
--- /dev/null
+++ b/src/pages/campaigns.tsx
@@ -0,0 +1,12 @@
+import { TopBar } from "@/components/layout/top-bar";
+
+export const CampaignsPage = () => {
+ return (
+
+
+
+
Campaigns — coming soon
+
+
+ );
+};
diff --git a/src/pages/lead-workspace.tsx b/src/pages/lead-workspace.tsx
new file mode 100644
index 0000000..cddaca5
--- /dev/null
+++ b/src/pages/lead-workspace.tsx
@@ -0,0 +1,12 @@
+import { TopBar } from "@/components/layout/top-bar";
+
+export const LeadWorkspacePage = () => {
+ return (
+
+
+
+
Lead Workspace — coming soon
+
+
+ );
+};
diff --git a/src/pages/login.tsx b/src/pages/login.tsx
new file mode 100644
index 0000000..1222273
--- /dev/null
+++ b/src/pages/login.tsx
@@ -0,0 +1,3 @@
+export const LoginPage = () => {
+ return Login placeholder
;
+};
diff --git a/src/pages/outreach.tsx b/src/pages/outreach.tsx
new file mode 100644
index 0000000..f52321f
--- /dev/null
+++ b/src/pages/outreach.tsx
@@ -0,0 +1,12 @@
+import { TopBar } from "@/components/layout/top-bar";
+
+export const OutreachPage = () => {
+ return (
+
+
+
+
Outreach — coming soon
+
+
+ );
+};