Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion development/backend/global-settings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -618,14 +618,18 @@ export const smtpSettings: GlobalSettingsModule = {
settings: [
{
key: 'smtp.host',
name: 'SMTP Host',
defaultValue: '',
type: 'string',
description: 'SMTP server hostname (e.g., smtp.gmail.com)',
encrypted: false,
required: true
},
{
key: 'smtp.password',
name: 'SMTP Password',
defaultValue: '',
type: 'string',
description: 'SMTP authentication password',
encrypted: true,
required: true
Expand All @@ -635,6 +639,20 @@ export const smtpSettings: GlobalSettingsModule = {
};
```

### Setting Properties

Each setting in the `settings` array requires these properties:

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `key` | `string` | Yes | Unique identifier using dot notation (e.g., `smtp.host`) |
| `name` | `string` | Yes | Human-readable label for frontend display (e.g., `SMTP Host`) |
| `defaultValue` | `string \| number \| boolean` | Yes | Default value when setting is created |
| `type` | `'string' \| 'number' \| 'boolean'` | Yes | Value type for validation and UI rendering |
| `description` | `string` | Yes | Help text explaining what the setting does |
| `encrypted` | `boolean` | Yes | Whether to encrypt the value in the database |
| `required` | `boolean` | Yes | Whether the setting must have a non-empty value |

### Startup Behavior

When the server starts:
Expand Down Expand Up @@ -750,14 +768,18 @@ export const myServiceSettings: GlobalSettingsModule = {
settings: [
{
key: 'my-service.api_key',
name: 'API Key',
defaultValue: '',
type: 'string',
description: 'API key for My Service',
encrypted: true,
required: true
},
{
key: 'my-service.enabled',
defaultValue: 'false',
name: 'Enable Service',
defaultValue: false,
type: 'boolean',
description: 'Enable My Service integration',
encrypted: false,
required: false
Expand Down
128 changes: 128 additions & 0 deletions development/frontend/ui/siteHeader-with-breadcrumbs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: SiteHeader with Breadcrumbs
description: Guide for implementing dynamic breadcrumb navigation in the dashboard header.
---


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.

### BreadcrumbItem Interface

```typescript
interface BreadcrumbItem {
label: string // Display text
href?: string // Optional link - omit for current page
}
```

### Returned Values

| Property | Type | Description |
|----------|------|-------------|
| `breadcrumbs` | `Readonly<Ref<BreadcrumbItem[]>>` | Current breadcrumb items |
| `setBreadcrumbs` | `(items: BreadcrumbItem[]) => void` | Set the breadcrumb trail |
| `clearBreadcrumbs` | `() => void` | Clear all breadcrumbs |

## Usage Patterns

### Static Pages

For pages with fixed titles like Dashboard or Settings:

```vue
<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:

```vue
<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:

```vue
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:

```vue
<template>
<DashboardLayout>
<!-- Page content -->
</DashboardLayout>
</template>
```

## Related Documentation

- [UI Design System](/development/frontend/ui/) - Component design patterns
- [Frontend Architecture](/development/frontend/architecture) - View and composable guidelines
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
"/development/frontend/ui/design-system-pagination",
"/development/frontend/ui/design-system-structured-data",
"/development/frontend/ui/design-system-table",
"/development/frontend/ui/custom-ui-components"
"/development/frontend/ui/custom-ui-components",
"/development/frontend/ui/siteHeader-with-breadcrumbs"
]
}
]
Expand Down
Loading