diff --git a/src/components/shell/sidebar.tsx b/src/components/shell/sidebar.tsx
new file mode 100644
index 0000000..ebc7d78
--- /dev/null
+++ b/src/components/shell/sidebar.tsx
@@ -0,0 +1,254 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { ChevronDown, Menu, Search, Star, X } from "lucide-react";
+import { useEffect, useMemo, useState } from "react";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Logo } from "@/components/common/logo";
+import { cn } from "@/lib/utils";
+import { groupRoutes, routeItems, sidebarRoutes } from "@/lib/routes";
+import { useUiStore } from "@/stores/ui-store";
+
+export function Sidebar() {
+ const collapsed = useUiStore((state) => state.sidebarCollapsed);
+ const toggleSidebar = useUiStore((state) => state.toggleSidebar);
+
+ return (
+
+ );
+}
+
+export function MobileSidebar() {
+ const open = useUiStore((state) => state.mobileSidebarOpen);
+ const setOpen = useUiStore((state) => state.setMobileSidebarOpen);
+ const pathname = usePathname();
+
+ useEffect(() => {
+ setOpen(false);
+ }, [pathname, setOpen]);
+
+ useEffect(() => {
+ if (!open) return;
+ document.body.style.overflow = "hidden";
+ const onKeyDown = (event: KeyboardEvent) => {
+ if (event.key === "Escape") setOpen(false);
+ };
+ window.addEventListener("keydown", onKeyDown);
+ return () => {
+ document.body.style.overflow = "";
+ window.removeEventListener("keydown", onKeyDown);
+ };
+ }, [open, setOpen]);
+
+ return (
+
+
setOpen(false)}
+ />
+
+
+ );
+}
+
+function SidebarBody({
+ collapsed,
+ headerAction,
+ onNavigate,
+}: {
+ collapsed: boolean;
+ headerAction: React.ReactNode;
+ onNavigate?: () => void;
+}) {
+ const pathname = usePathname();
+ const favorites = useUiStore((state) => state.favorites);
+ const recent = useUiStore((state) => state.recent);
+ const [filter, setFilter] = useState("");
+
+ const favoritesRoutes = routeItems.filter((item) => favorites.includes(item.path));
+ const recentRoutes = routeItems.filter((item) => recent.includes(item.path));
+ const visible = useMemo(() => {
+ if (!filter) return sidebarRoutes;
+ const term = filter.toLowerCase();
+ return routeItems.filter((item) =>
+ [item.label, item.category, item.description, ...item.keywords].some((value) =>
+ value.toLowerCase().includes(term),
+ ),
+ );
+ }, [filter]);
+ const groups = groupRoutes(visible);
+
+ return (
+ <>
+
+
+
+
+ {headerAction}
+
+ {!collapsed ? (
+
+
+
+ setFilter(event.target.value)}
+ placeholder="Find tools"
+ className="h-8 pl-8"
+ />
+
+
+ ) : null}
+
+ {!collapsed && !filter ? (
+
+ ) : null}
+ {!collapsed && !filter ? (
+
+ ) : null}
+ {Object.entries(groups).map(([title, routes]) => (
+
+ ))}
+
+ >
+ );
+}
+
+function SidebarSection({
+ title,
+ routes,
+ pathname,
+ collapsed,
+ icon,
+ onNavigate,
+}: {
+ title: string;
+ routes: typeof routeItems;
+ pathname: string;
+ collapsed: boolean;
+ icon?: "star";
+ onNavigate?: () => void;
+}) {
+ if (!routes.length) return null;
+ return (
+
+ {!collapsed ? (
+
+ {icon === "star" ? (
+
+ ) : (
+
+ )}
+ {title}
+
+ ) : null}
+
+ {routes.map((route) => {
+ const Icon = route.icon;
+ const active =
+ pathname === route.path ||
+ (route.path !== "/dashboard" && pathname.startsWith(`${route.path}/`));
+ return (
+
+ {active ? (
+
+ ) : null}
+
+ {!collapsed ? {route.label} : null}
+
+ );
+ })}
+
+
+ );
+}