Skip to main content
The SiteHeader component displays a sidebar toggle and breadcrumb navigation at the top of each dashboard page. Views set their breadcrumbs using the useBreadcrumbs composable.

Component Locations

services/frontend/src/
 ├─ composables/
    └─ useBreadcrumbs.ts     # Shared breadcrumb state management
 ├─ components/
    ├─ SiteHeader.vue        # Header with sidebar trigger + breadcrumbs
    └─ DashboardLayout.vue   # Layout wrapper that includes SiteHeader

Composable API

The useBreadcrumbs composable manages breadcrumb state across all views.
interface BreadcrumbItem {
  label: string   // Display text
  href?: string   // Optional link - omit for current page
}

Returned Values

PropertyTypeDescription
breadcrumbsReadonly<Ref<BreadcrumbItem[]>>Current breadcrumb items
setBreadcrumbs(items: BreadcrumbItem[]) => voidSet the breadcrumb trail
clearBreadcrumbs() => voidClear all breadcrumbs

Usage Patterns

Static Pages

For pages with fixed titles like Dashboard or Settings:
<script setup lang="ts">
import { onMounted } from 'vue'
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'

const { setBreadcrumbs } = useBreadcrumbs()

onMounted(() => {
  setBreadcrumbs([{ label: 'Dashboard' }])
})
</script>

Detail Pages with Dynamic Data

For pages that load data (team detail, server view), set breadcrumbs twice:
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
import { TeamService } from '@/services/teamService'

const route = useRoute()
const { setBreadcrumbs } = useBreadcrumbs()
const team = ref(null)

onMounted(async () => {
  // Initial loading state
  setBreadcrumbs([
    { label: 'Teams', href: '/teams' },
    { label: 'Loading...' }
  ])

  // Fetch and update with actual name
  team.value = await TeamService.getTeam(route.params.id)
  setBreadcrumbs([
    { label: 'Teams', href: '/teams' },
    { label: team.value.name }
  ])
})
</script>

Nested Pages

For deeply nested pages, include the full path:
setBreadcrumbs([
  { label: 'MCP Catalog', href: '/admin/mcp-server-catalog' },
  { label: server.name, href: `/admin/mcp-server-catalog/view/${serverId}` },
  { label: 'Edit' }
])

Header Layout

The SiteHeader renders in this order:
  1. SidebarTrigger - Toggle button for collapsing/expanding sidebar
  2. Separator - Vertical divider
  3. Breadcrumbs - Navigation trail with responsive visibility
On mobile, intermediate breadcrumb items are hidden, showing only the current page.

View Template

Views no longer pass a :title prop to DashboardLayout:
<template>
  <DashboardLayout>
    <!-- Page content -->
  </DashboardLayout>
</template>