diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 3693817..863030b 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -1,20 +1,15 @@
import type { Metadata, Viewport } from "next";
import { GeistSans } from "geist/font/sans";
+import { ThemeProvider } from "@/components/theme-provider";
+import { AppShell } from "@/components/app-shell";
+import { Toaster } from "@/components/ui/sonner";
import "./globals.css";
-import { Geist } from "next/font/google";
-import { cn } from "@/lib/utils";
-
-const geist = Geist({subsets:['latin'],variable:'--font-sans'});
export const metadata: Metadata = {
title: "cm WhatsApp Bot",
description: "Self-hosted WhatsApp reminder bot",
applicationName: "cm WhatsApp Bot",
- appleWebApp: {
- capable: true,
- title: "cm WA Bot",
- statusBarStyle: "default",
- },
+ appleWebApp: { capable: true, title: "cm WA Bot", statusBarStyle: "default" },
};
export const viewport: Viewport = {
@@ -26,8 +21,13 @@ export const viewport: Viewport = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
-
-
{children}
+
+
+
+ {children}
+
+
+
);
}
diff --git a/apps/web/src/components/app-shell.tsx b/apps/web/src/components/app-shell.tsx
new file mode 100644
index 0000000..0a0cf8b
--- /dev/null
+++ b/apps/web/src/components/app-shell.tsx
@@ -0,0 +1,134 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { cn } from "@/lib/utils";
+import { NAV_ITEMS } from "@/components/nav-config";
+
+// ---------------------------------------------------------------------------
+// Bottom nav (mobile only — hidden sm+)
+// ---------------------------------------------------------------------------
+function BottomNav() {
+ const pathname = usePathname();
+
+ return (
+
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Sidebar (desktop only — hidden below sm)
+// ---------------------------------------------------------------------------
+function Sidebar() {
+ const pathname = usePathname();
+
+ return (
+
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Top app bar (mobile only)
+// ---------------------------------------------------------------------------
+function TopAppBar() {
+ const pathname = usePathname();
+ const currentItem = NAV_ITEMS.find(({ href }) =>
+ href === "/" ? pathname === "/" : pathname.startsWith(href),
+ );
+ const title = currentItem?.label ?? "cm WhatsApp Bot";
+
+ return (
+
+ );
+}
+
+// ---------------------------------------------------------------------------
+// AppShell — the outer container
+// ---------------------------------------------------------------------------
+interface AppShellProps {
+ children: React.ReactNode;
+}
+
+export function AppShell({ children }: AppShellProps) {
+ return (
+ <>
+ {/* Desktop sidebar */}
+
+
+ {/* Mobile top app bar */}
+
+
+ {/* Main content
+ Mobile: push down for top bar (pt-14), push up for bottom nav (pb-16)
+ Desktop: push right for sidebar (sm:pl-56), no top/bottom chrome offset */}
+
+ {children}
+
+
+ {/* Mobile bottom nav */}
+
+ >
+ );
+}
diff --git a/apps/web/src/components/nav-config.ts b/apps/web/src/components/nav-config.ts
new file mode 100644
index 0000000..00b97c2
--- /dev/null
+++ b/apps/web/src/components/nav-config.ts
@@ -0,0 +1,16 @@
+import { Home, Smartphone, Calendar, Settings } from "lucide-react";
+import type { LucideIcon } from "lucide-react";
+
+export interface NavItem {
+ key: string;
+ href: string;
+ label: string;
+ icon: LucideIcon;
+}
+
+export const NAV_ITEMS: NavItem[] = [
+ { key: "dashboard", href: "/", label: "Dashboard", icon: Home },
+ { key: "accounts", href: "/accounts", label: "Accounts", icon: Smartphone },
+ { key: "reminders", href: "/reminders", label: "Reminders", icon: Calendar },
+ { key: "settings", href: "/settings", label: "Settings", icon: Settings },
+];
diff --git a/apps/web/src/components/theme-provider.tsx b/apps/web/src/components/theme-provider.tsx
new file mode 100644
index 0000000..fcb9b9d
--- /dev/null
+++ b/apps/web/src/components/theme-provider.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { ThemeProvider as NextThemesProvider } from "next-themes";
+import type { ComponentProps } from "react";
+
+type ThemeProviderProps = ComponentProps;
+
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ return (
+
+ {children}
+
+ );
+}