QUESTPIE

Sidebar

Configure the admin sidebar — sections, collection items, global items, and external links.

The sidebar controls admin navigation. Configure it in config/admin.ts — define sections and items under the sidebar key.

Basic Setup

config/admin.ts
import { adminConfig } from "#questpie/factories";

export default adminConfig({
	sidebar: {
		sections: [
			{ id: "overview", title: { en: "Overview" } },
			{ id: "content", title: { en: "Content" } },
		],
		items: [
			{
				sectionId: "overview",
				type: "link",
				label: { en: "Dashboard" },
				href: "/admin",
				icon: { type: "icon", props: { name: "ph:house" } },
			},
			{
				sectionId: "content",
				type: "collection",
				collection: "posts",
			},
		],
	},
});

Sections

Sections group sidebar items:

sections: [
	{ id: "overview", title: { en: "Overview", sk: "Prehľad" } },
	{ id: "operations", title: { en: "Operations", sk: "Prevádzka" } },
	{ id: "content", title: { en: "Content", sk: "Obsah" } },
	{ id: "team", title: { en: "Team", sk: "Tím" } },
];

Item Types

Collection

Links to a collection list view. Label and icon are read from the collection's .admin() config:

{ sectionId: "content", type: "collection", collection: "posts" }

Global

Links to a global edit form:

{ sectionId: "overview", type: "global", global: "siteSettings" }

Custom link with icon:

{
  sectionId: "external",
  type: "link",
  label: { en: "Open Website" },
  href: "/",
  external: true,
  icon: { type: "icon", props: { name: "ph:arrow-square-out" } },
}

Real-World Example

From the barbershop:

config/admin.ts
import { adminConfig } from "#questpie/factories";

export default adminConfig({
	sidebar: {
		sections: [
			{ id: "overview", title: { en: "Overview" } },
			{ id: "operations", title: { en: "Operations" } },
			{ id: "content", title: { en: "Content" } },
			{ id: "team", title: { en: "Team" } },
			{ id: "external", title: { en: "External" } },
			{ id: "administration", title: { en: "Administration" } },
		],
		items: [
			{
				sectionId: "overview",
				type: "link",
				label: { en: "Dashboard" },
				href: "/admin",
				icon: { type: "icon", props: { name: "ph:house" } },
			},
			{ sectionId: "overview", type: "global", global: "siteSettings" },
			{
				sectionId: "operations",
				type: "collection",
				collection: "appointments",
			},
			{ sectionId: "operations", type: "collection", collection: "reviews" },
			{ sectionId: "content", type: "collection", collection: "pages" },
			{ sectionId: "content", type: "collection", collection: "services" },
			{ sectionId: "team", type: "collection", collection: "barbers" },
			{
				sectionId: "external",
				type: "link",
				label: { en: "Open Website" },
				href: "/",
				external: true,
				icon: { type: "icon", props: { name: "ph:arrow-square-out" } },
			},
		],
	},
});

Chrome Overrides

To customize sidebar chrome without modifying your app shell, use file-first component overrides.

Brand area

Replace the logo + name area:

questpie/admin/components/admin-sidebar-brand.tsx
import type { AdminSidebarBrandProps } from "@questpie/admin/client";

export default function SidebarBrand({
	name,
	collapsed,
}: AdminSidebarBrandProps) {
	return (
		<div className="flex items-center gap-2">
			<img src="/logo.svg" alt={name} className="size-6 shrink-0" />
			{!collapsed && <span className="font-bold">{name}</span>}
		</div>
	);
}

Replace every navigation item row:

questpie/admin/components/admin-sidebar-nav-item.tsx
import type { AdminSidebarNavItemProps } from "@questpie/admin/client";

export default function NavItem({
	item,
	isActive,
	collapsed,
}: AdminSidebarNavItemProps) {
	return (
		<a
			href={item.href}
			className={`flex items-center gap-2 px-3 py-2 text-sm ${isActive ? "font-bold" : ""}`}
		>
			{!collapsed && (
				<span>
					{typeof item.label === "string" ? item.label : item.label.en}
				</span>
			)}
		</a>
	);
}

Both overrides follow the same three-tier priority: runtime prop > file-first > built-in.

Use a normal React component as the default export for these files. React.lazy(...) is fine too. Do not default-export a raw () => import("...") loader function for reserved sidebar overrides.

Module Contributions

Modules can contribute sidebar items. The adminModule adds an "Administration" section with user management. The auditModule adds an audit log item to that section. Your project-level sidebar merges with these contributions.

On this page