ObjectUIObjectUI
Core

Application Schema (AppComponentSchema)

Configure your entire application with navigation, branding, and global settings

Application Schema

The AppComponentSchema defines the top-level configuration for your entire ObjectUI application, including navigation menus, branding, layout strategies, and global actions.

Overview

AppComponentSchema provides a declarative way to configure:

  • Navigation menus - Hierarchical menu structures with icons and badges
  • Branding - Logo, title, favicon
  • Layout strategies - Sidebar, header, or empty layout
  • Global actions - User menu, global toolbar buttons

Interactive Examples

Sidebar Navigation

Dashboard
Contacts
128
Opportunities
Marketing
Campaigns
Email Templates
Settings

Application Header Bar

Application Header

Acme CRM
JD
John Doejohn@acme.com

Basic Usage

import type { AppComponentSchema } from '@object-ui/types';

const app: AppComponentSchema = {
  type: 'app',
  name: 'my-crm',
  title: 'My CRM Application',
  logo: '/logo.svg',
  favicon: '/favicon.ico',
  layout: 'sidebar',
  
  menu: [
    {
      type: 'item',
      label: 'Dashboard',
      icon: 'layout-dashboard',
      path: '/dashboard'
    }
  ],
  
  actions: [
    {
      type: 'user',
      label: 'John Doe',
      avatar: '/avatar.jpg'
    }
  ]
};

Properties

The tables in this section describe AppComponentSchema, declared by @object-ui/types (packages/types/src/app.ts). They group its properties by topic; the declaration remains the complete list.

Basic Configuration

PropertyTypeDescription
type'app'Component type identifier (required)
namestringApplication system identifier
titlestringDisplay title shown in browser
descriptionstringApplication description
logostringLogo URL or icon name
faviconstringFavicon URL

Layout Configuration

PropertyTypeDefaultDescription
layout'sidebar' | 'header' | 'empty''sidebar'Global layout strategy

Layout Options:

  • sidebar - Standard admin layout with left sidebar navigation
  • header - Top navigation bar only
  • empty - No layout, pages handle their own structure

The menu property accepts an array of AppMenuItem objects:

interface AppMenuItem {
  type?: 'item' | 'group' | 'separator';
  label?: string;
  icon?: string;          // Lucide icon name
  path?: string;          // Route path
  href?: string;          // External link
  children?: AppMenuItem[];  // Submenu items
  badge?: string | number;
  hidden?: boolean | string; // Visibility condition
}

Item - Single navigation link

{
  "type": "item",
  "label": "Dashboard",
  "icon": "layout-dashboard",
  "path": "/dashboard",
  "badge": "New"
}

Group - Collapsible menu group

{
  "type": "group",
  "label": "Sales",
  "icon": "dollar-sign",
  "children": [
    { "type": "item", "label": "Leads", "path": "/leads" },
    { "type": "item", "label": "Deals", "path": "/deals" }
  ]
}

Separator - Visual separator

{
  "type": "separator"
}

Global Actions

The actions property defines global toolbar buttons:

// `AppAction.items` uses the navigation-item shape documented under "Navigation
// Menu" above — declared and published as `AppMenuItem`. The bare `MenuItem`
// export is the unrelated overlay menu type used by `ui:dropdown-menu`.
import type { AppMenuItem } from '@object-ui/types';

interface AppAction {
  type: 'button' | 'dropdown' | 'user';
  label?: string;
  icon?: string;
  onClick?: never;        // RETIRED (objectui#7344): the handler-expression string is refused by name — author an action:button node instead
  avatar?: string;        // For type='user'
  description?: string;   // For type='user'
  items?: AppMenuItem[];  // For type='dropdown' or 'user'
  shortcut?: string;      // Keyboard shortcut
  variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
  size?: 'default' | 'sm' | 'lg' | 'icon';
}

Complete Example

import type { AppComponentSchema } from '@object-ui/types';

const crm: AppComponentSchema = {
  type: 'app',
  name: 'acme-crm',
  title: 'Acme CRM',
  description: 'Customer Relationship Management System',
  logo: '/acme-logo.svg',
  favicon: '/favicon.ico',
  layout: 'sidebar',
  
  menu: [
    {
      type: 'item',
      label: 'Dashboard',
      icon: 'layout-dashboard',
      path: '/dashboard'
    },
    {
      type: 'separator'
    },
    {
      type: 'group',
      label: 'Sales',
      icon: 'dollar-sign',
      children: [
        {
          type: 'item',
          label: 'Leads',
          icon: 'users',
          path: '/leads',
          badge: 12
        },
        {
          type: 'item',
          label: 'Opportunities',
          icon: 'target',
          path: '/opportunities'
        },
        {
          type: 'item',
          label: 'Quotes',
          icon: 'file-text',
          path: '/quotes'
        }
      ]
    },
    {
      type: 'group',
      label: 'Marketing',
      icon: 'megaphone',
      children: [
        {
          type: 'item',
          label: 'Campaigns',
          path: '/campaigns'
        },
        {
          type: 'item',
          label: 'Email Templates',
          path: '/templates'
        }
      ]
    },
    {
      type: 'separator'
    },
    {
      type: 'item',
      label: 'Settings',
      icon: 'settings',
      path: '/settings',
      hidden: '${user.role !== "admin"}'
    }
  ],
  
  actions: [
    {
      type: 'button',
      label: 'Quick Actions',
      icon: 'zap',
      variant: 'outline'
    },
    {
      type: 'user',
      label: 'John Doe',
      avatar: '/avatars/john.jpg',
      description: 'john@acme.com',
      items: [
        {
          type: 'item',
          label: 'Profile',
          icon: 'user',
          path: '/profile'
        },
        {
          type: 'item',
          label: 'Settings',
          icon: 'settings',
          path: '/settings'
        },
        {
          type: 'separator'
        },
        {
          type: 'item',
          label: 'Logout',
          icon: 'log-out',
          path: '/logout'
        }
      ]
    }
  ]
};

Runtime Validation

Use Zod validation to ensure your app configuration is correct:

import { AppComponentSchema } from '@object-ui/types/zod';

const myAppConfig = {
  type: 'app',
  name: 'my-crm',
  title: 'My CRM Application',
};

const result = AppComponentSchema.safeParse(myAppConfig);

if (result.success) {
  console.log('Valid app configuration');
} else {
  console.error('Validation errors:', result.error);
}

Conditional Navigation

Use expression syntax to show/hide menu items based on user permissions:

{
  "type": "item",
  "label": "Admin Panel",
  "path": "/admin",
  "hidden": "${user.role !== 'admin'}"
}

Use Cases

AppComponentSchema is ideal for:

  • Multi-page applications - Configure complex application structures with multiple routes
  • Admin dashboards - Create comprehensive admin panels with role-based navigation
  • CRM systems - Build customer relationship management interfaces
  • Internal tools - Develop enterprise internal tools with centralized navigation
  • SaaS products - Configure multi-tenant applications with customizable layouts

Best Practices

  1. Use semantic icons - Choose Lucide icons that clearly represent the section
  2. Group related items - Use menu groups to organize navigation
  3. Limit top-level items - Keep the main menu concise (5-7 items)
  4. Add badges for notifications - Show counts or status indicators
  5. Hide admin features - Use conditional visibility for role-based access
  6. Provide keyboard shortcuts - Add shortcuts for frequently used actions

On this page