Apps
Apps
Tenant apps are Svelte components discovered from src/apps/**/+<lower_snake_case>.svelte. Each filename is the canonical app ID.
Apps compile into the client bundle and render with the signed-in user's policy context.
Source layout
src/apps/
├── +operations.svelte
└── finance/
├── +group.ts
└── +payroll.svelte Group metadata is optional. A group directory owns the group ID; each app filename owns its app ID. No registration module is authored.
Static metadata
Each app declares literal metadata in <svelte:head>:
<svelte:head>
<title>Operations</title>
<meta name="description" content="Manage daily operations" />
<meta name="pod:icon" content="lucide:briefcase" />
<meta name="pod:thumbnail" content="https://cdn.example.com/operations-card.webp" />
<meta name="pod:banner" content="https://cdn.example.com/operations-banner.webp" />
</svelte:head> The optional pod:thumbnail image appears in the root app gallery. The optional pod:banner image appears above the app and scrolls with the app surface. Both values must
be static URLs.
Page scaffold
Apps compose a Page scaffold with optional Page.Tab children. Use fill on the page or tab when a collection view should bound viewport-remainder height
(pair with pod:layout="contain" in the head).
Client access
<script lang="ts">
import { collectionClient } from '$pod/client';
import { Page } from '@norbital-ai/ui/page';
import { CollectionTable } from '@norbital-ai/ui/collection-table';
</script>
<svelte:head>
<title>Operations</title>
<meta name="pod:icon" content="lucide:briefcase" />
<meta name="pod:layout" content="contain" />
</svelte:head>
<Page title="Operations" description="Manage daily operations." fill>
<CollectionTable client={collectionClient} collectionName="sites" create>
{#snippet columns({ Column })}
<Column name="name" />
<Column name="client_name" />
<Column name="house_type" />
{/snippet}
</CollectionTable>
</Page> Every CollectionTable requires an explicit {#snippet columns({ Column })} — table UI does not auto-derive columns from the model. Prefer create / createForm on the table for standard create flows.
Keep server-only behavior in hooks, pipelines, integrations, automations, or remotes. App access is filtered by team policy, and collection operations use the same policy enforcement as other clients.