ObjectStackObjectStack

App Metadata

Define application containers with navigation, branding, and access control

App Metadata

An App is a logical container that bundles objects, views, pages, and dashboards into a cohesive application experience. It defines the navigation structure, branding, and access permissions.

Basic Structure

const crmApp = {
  name: 'crm',
  label: 'CRM',
  version: '1.0.0',
  description: 'Customer Relationship Management',
  icon: 'briefcase',
  active: true,

  branding: {
    primaryColor: '#1a73e8',
    logo: '/assets/crm-logo.svg',
    favicon: '/assets/favicon.ico',
  },

  navigation: [
    { id: 'nav_accounts', type: 'object', label: 'Accounts', objectName: 'account', icon: 'building' },
    { id: 'nav_contacts', type: 'object', label: 'Contacts', objectName: 'contact', icon: 'users' },
    { id: 'nav_opportunities', type: 'object', label: 'Opportunities', objectName: 'opportunity', icon: 'trending-up' },
    { id: 'nav_sales_dashboard', type: 'dashboard', label: 'Sales Dashboard', dashboardName: 'sales_overview', icon: 'bar-chart' },
  ],

  requiredPermissions: ['crm_access'],
};

App Properties

PropertyTypeRequiredDescription
namestringMachine name (snake_case)
labelstringDisplay name
versionstringoptionalApp version
descriptionstringoptionalApp description
iconstringoptionalApp icon (Lucide)
activebooleanoptionalIs app active (default: true)
isDefaultbooleanoptionalIs default app
navigationNavigationItem[]optionalNavigation tree
brandingAppBrandingoptionalVisual customization
requiredPermissionsstring[]optionalRequired permissions to access
homePageIdstringoptionalID of the navigation item to serve as the landing page
objectsunknown[]optionalObjects belonging to this app
apisunknown[]optionalCustom APIs belonging to this app
mobileNavigationobjectoptionalMobile-specific navigation

The navigation tree supports eight item types, combined to create rich menu structures. The most common are shown below (object, dashboard, page, url, group); the spec also defines report, action, and component items.

Object Navigation

Links to an object's list view:

{ id: 'nav_accounts', type: 'object', label: 'Accounts', objectName: 'account', icon: 'building', viewName: 'all_accounts' }

Three optional target fields refine where the entry lands (precedence: recordIdfiltersviewName):

  • viewName — anchor the entry to a named list view.
  • recordId — deep-link straight to one record ("My Profile"); supports {current_user_id} / {current_org_id} template variables.
  • filters — a one-off parameterized slice: the entry lands on the bare data surface (/:objectName/data) with each condition serialized as a removable filter[<field>]=<value> URL chip, not anchored to any saved view. Use it for drill-throughs and "assigned to me"-style links instead of authoring a view; values support the same template variables. The surface shows what row-level permissions allow — it is not a security feature.
{ id: 'nav_my_open', type: 'object', label: 'My Open Deals', objectName: 'opportunity',
  filters: { owner_id: '{current_user_id}', status: 'open' }, icon: 'user-check' }

Dashboard Navigation

Links to a dashboard:

{ id: 'nav_analytics', type: 'dashboard', label: 'Analytics', dashboardName: 'sales_overview', icon: 'bar-chart' }

Links to a custom page:

{ id: 'nav_settings', type: 'page', label: 'Settings', pageName: 'app_settings', icon: 'settings', params: { tab: 'general' } }

URL Navigation

Links to an external URL:

{ id: 'nav_help', type: 'url', label: 'Help Center', url: 'https://help.example.com', icon: 'help-circle', target: '_blank' }

Group Navigation

Groups items into collapsible sections with children:

{
  id: 'grp_sales',
  type: 'group',
  label: 'Sales',
  icon: 'dollar-sign',
  expanded: true,
  children: [
    { id: 'nav_accounts', type: 'object', label: 'Accounts', objectName: 'account', icon: 'building' },
    { id: 'nav_contacts', type: 'object', label: 'Contacts', objectName: 'contact', icon: 'users' },
    { id: 'nav_opportunities', type: 'object', label: 'Opportunities', objectName: 'opportunity', icon: 'trending-up' },
  ],
}

Common Navigation Properties

All navigation items share these base properties. Every item must declare a unique id (lowercase snake_case) — it is required by the schema and is referenced by homePageId and mobileNavigation.bottomNavItems:

PropertyTypeDescription
idstringUnique identifier (snake_case, required)
labelstringDisplay label
iconstringIcon name (Lucide)
ordernumberSort order within the same level (lower = first)
badgestring | numberBadge text or count displayed on the item
visibleExpressionVisibility predicate (CEL expression)
requiredPermissionsstring[]Permissions required to see/access this item
requiresObjectstringHide/disable unless the named object is registered
requiresServicestringHide/disable unless the named kernel service is registered

Branding

Customize the visual appearance of the app:

branding: {
  primaryColor: '#1a73e8',    // Hex color code
  logo: '/assets/logo.svg',   // Logo URL
  favicon: '/assets/icon.ico', // Favicon URL
}
PropertyTypeDescription
primaryColorstringPrimary brand color (hex)
logostringLogo image URL
faviconstringFavicon URL

Mobile Navigation

Configure mobile-specific navigation behavior:

mobileNavigation: {
  mode: 'bottom_nav',
  bottomNavItems: ['nav_home', 'nav_accounts', 'nav_contacts', 'nav_settings'],
}

mode accepts 'drawer' (default), 'bottom_nav', or 'hamburger'. bottomNavItems lists the navigation item ids to surface in the bottom bar (max 5).

Complete Example

const projectApp = {
  name: 'project_management',
  label: 'Project Management',
  version: '2.0.0',
  description: 'Track projects, tasks, and team workload',
  icon: 'folder-kanban',
  active: true,

  branding: {
    primaryColor: '#6366f1',
    logo: '/assets/pm-logo.svg',
  },

  navigation: [
    {
      id: 'nav_home',
      type: 'page',
      label: 'Home',
      pageName: 'pm_home',
      icon: 'home',
    },
    {
      id: 'grp_projects',
      type: 'group',
      label: 'Projects',
      icon: 'folder',
      expanded: true,
      children: [
        { id: 'nav_projects', type: 'object', label: 'Projects', objectName: 'project', icon: 'folder' },
        { id: 'nav_tasks', type: 'object', label: 'Tasks', objectName: 'project_task', icon: 'check-square', viewName: 'task_board' },
        { id: 'nav_milestones', type: 'object', label: 'Milestones', objectName: 'milestone', icon: 'flag' },
      ],
    },
    {
      id: 'grp_reports',
      type: 'group',
      label: 'Reports',
      icon: 'bar-chart',
      children: [
        { id: 'nav_overview', type: 'dashboard', label: 'Overview', dashboardName: 'project_overview', icon: 'layout-dashboard' },
        { id: 'nav_team_workload', type: 'dashboard', label: 'Team Workload', dashboardName: 'team_workload', icon: 'users' },
      ],
    },
    {
      id: 'nav_docs',
      type: 'url',
      label: 'Documentation',
      url: 'https://docs.example.com/pm',
      icon: 'book-open',
      target: '_blank',
    },
  ],

  requiredPermissions: ['pm_access'],
  homePageId: 'nav_home',
};

On this page