/iblai-vibe-org-metadata
First time here? If iblai.env has no ARCHITECTURE=, run /iblai-vibe-start first (four questions; two minutes) — it decides single-org / multi-org / headless and who signs in, and every skill reads the answer.
Every organization has one public metadata object. The ibl.ai OS keeps
its own settings there (default agent, help center URL, chat width, feature
toggles, the sign-in page branding), and your app can keep its own keys
beside them. It is how an app remembers org-level choices — which agent the
home page uses, what the app is called, a welcome message — without a
database.
Common setup (brand, conventions, env files, verification): see docs/skill-setup.md.
The two rules
- PUT replaces the whole object.
PUT …/orgs/{org}/metadata/ with only
your keys silently deletes overall_default_mentor, help_center_url,
auth_web_mentorai, every toggle — and breaks the OS for that org. The
helper in this skill always GET → merge → PUT, re-reading right before
it writes.
- It is a public read.
GET …/orgs/{org}/metadata/ needs no auth. Never
store a secret, a token, a price you do not want visible, or a person's
data there. Ids and display strings only.
Writes need an org admin; the platform answers 403 otherwise.
What you get
useOrgSettings<T>() in lib/iblai/metadata.ts (installed by
/iblai-vibe-user-metadata; the two share the file) — typed read/merge
under metadata.apps.<slug>, GET-merge-PUT on write.
OrgSettingsForm — an admin card (app name, welcome message, support URL)
for /admin/organization.
- vibe-starter's
/setup stores defaultAgentId, appName, and
setupCompletedAt here; the home page reads defaultAgentId when
NEXT_PUBLIC_DEFAULT_AGENT_ID is empty.
Where branding lives instead
| Setting |
Where |
Skill |
| Org display name, light/dark logos, support email, Help Center toggle + URL |
SDK Account → Organization tab (OrganizationTab) |
/iblai-vibe-account |
| Default agent, Help/Accessibility menus, Community Agents, Report content, Chat History Export |
SDK Account → Advanced tab — these are the OS's keys in this same object |
/iblai-vibe-account |
Sign-in page title, logo, headline, footer credit, policy links (auth_web_*) |
written by /iblai-vibe-auth Step 2 |
/iblai-vibe-auth |
| Your app's own settings |
apps.<slug> via this skill |
here |
Step 1: Install
useOrgSettings ships in lib/iblai/metadata.ts — run
/iblai-vibe-user-metadata Step 2 if the app does not have it. Then render
assets/org-settings.tsx.j2 → components/settings/org-settings.tsx (needs
shadcn card, input, label).
Step 2: Use it
"use client";
import { useOrgSettings } from "@/lib/iblai/metadata";
type MyOrgSettings = { welcomeMessage?: string; supportUrl?: string };
export function Welcome() {
const { settings } = useOrgSettings<MyOrgSettings>({ welcomeMessage: "", supportUrl: "" });
return settings.welcomeMessage ? <p>{settings.welcomeMessage}</p> : null;
}
Admins save with update({ welcomeMessage: "…" }); every member reads it.
Mount <OrgSettingsForm /> on an admin-only page (/iblai-vibe-admin).
Step 3: Add your own keys
Extend OrgSettings in lib/iblai/metadata.ts and the form. Keep values
JSON-serializable and small; this object is fetched by every ibl.ai front
end that opens the org.
Verify
pnpm typecheck && pnpm test.
- Before and after saving, compare
curl -s https://api.$DOMAIN/dm/api/core/orgs/$PLATFORM/metadata/ | python3 -m json.tool —
only metadata.apps.<slug> changed; overall_default_mentor and the
auth_web_* blocks are intact.
- A non-admin's save fails with a toast, not a crash.
Platform data
| Hook / call |
Purpose |
useGetTenantMetadataQuery([{ org }]) |
the object (public) |
useUpdateTenantMetadataMutation() → ([{ org, requestBody: { metadata } }]) |
PUT (replace — always merge first) |
useTenantMetadata() (web-utils) |
the SDK's cached view of the same object |
GET/PUT https://api.<domain>/dm/api/core/orgs/{org}/metadata/ |
REST |
REST reference: iblai-api-org.
Related skills
/iblai-vibe-user-metadata — per-user twin
/iblai-vibe-account, /iblai-vibe-admin — where to mount the form
/iblai-vibe-auth — the sign-in page branding keys
1---2name: iblai-vibe-org-metadata3description: Store custom organization-wide settings for your app on the ibl.ai platform — app name, welcome message, support URL, the default agent, any per-org configuration — in the org's metadata object with a GET-merge-PUT helper that never drops the OS's own keys, plus where branding (name, logos, support email, help center) lives instead. Use when the user mentions organization settings, org-level config, per-organization settings, white-label, app settings for the whole org, or a setting every member should see. For per-user data see /iblai-vibe-user-metadata; for the SDK Organization tab see /iblai-vibe-account.4---56# /iblai-vibe-org-metadata78> **First time here?** If `iblai.env` has no `ARCHITECTURE=`, run `/iblai-vibe-start` first (four questions; two minutes) — it decides single-org / multi-org / headless and who signs in, and every skill reads the answer.910Every organization has **one public metadata object**. The ibl.ai OS keeps11its own settings there (default agent, help center URL, chat width, feature12toggles, the sign-in page branding), and your app can keep its own keys13beside them. It is how an app remembers org-level choices — which agent the14home page uses, what the app is called, a welcome message — without a15database.16171819> **Common setup (brand, conventions, env files, verification):** see [docs/skill-setup.md](https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/docs/skill-setup.md).2021## The two rules22231. **PUT replaces the whole object.** `PUT …/orgs/{org}/metadata/` with only24 your keys silently deletes `overall_default_mentor`, `help_center_url`,25 `auth_web_mentorai`, every toggle — and breaks the OS for that org. The26 helper in this skill always **GET → merge → PUT**, re-reading right before27 it writes.282. **It is a public read.** `GET …/orgs/{org}/metadata/` needs no auth. Never29 store a secret, a token, a price you do not want visible, or a person's30 data there. Ids and display strings only.3132Writes need an org admin; the platform answers `403` otherwise.3334## What you get3536- `useOrgSettings<T>()` in `lib/iblai/metadata.ts` (installed by37 `/iblai-vibe-user-metadata`; the two share the file) — typed read/merge38 under `metadata.apps.<slug>`, GET-merge-PUT on write.39- `OrgSettingsForm` — an admin card (app name, welcome message, support URL)40 for `/admin/organization`.41- vibe-starter's `/setup` stores `defaultAgentId`, `appName`, and42 `setupCompletedAt` here; the home page reads `defaultAgentId` when43 `NEXT_PUBLIC_DEFAULT_AGENT_ID` is empty.4445## Where branding lives instead4647| Setting | Where | Skill |48|---|---|---|49| Org display name, light/dark logos, support email, Help Center toggle + URL | SDK `Account` → **Organization** tab (`OrganizationTab`) | `/iblai-vibe-account` |50| Default agent, Help/Accessibility menus, Community Agents, Report content, Chat History Export | SDK `Account` → **Advanced** tab — these are the OS's keys in this same object | `/iblai-vibe-account` |51| Sign-in page title, logo, headline, footer credit, policy links (`auth_web_*`) | written by `/iblai-vibe-auth` Step 2 | `/iblai-vibe-auth` |52| Your app's own settings | `apps.<slug>` via this skill | here |5354## Step 1: Install5556`useOrgSettings` ships in `lib/iblai/metadata.ts` — run57`/iblai-vibe-user-metadata` Step 2 if the app does not have it. Then render58`assets/org-settings.tsx.j2` → `components/settings/org-settings.tsx` (needs59shadcn `card`, `input`, `label`).6061## Step 2: Use it6263```tsx64"use client";6566import { useOrgSettings } from "@/lib/iblai/metadata";6768type MyOrgSettings = { welcomeMessage?: string; supportUrl?: string };6970export function Welcome() {71 const { settings } = useOrgSettings<MyOrgSettings>({ welcomeMessage: "", supportUrl: "" });72 return settings.welcomeMessage ? <p>{settings.welcomeMessage}</p> : null;73}74```7576Admins save with `update({ welcomeMessage: "…" })`; every member reads it.77Mount `<OrgSettingsForm />` on an admin-only page (`/iblai-vibe-admin`).7879## Step 3: Add your own keys8081Extend `OrgSettings` in `lib/iblai/metadata.ts` and the form. Keep values82JSON-serializable and small; this object is fetched by every ibl.ai front83end that opens the org.8485## Verify86871. `pnpm typecheck && pnpm test`.882. Before and after saving, compare89 `curl -s https://api.$DOMAIN/dm/api/core/orgs/$PLATFORM/metadata/ | python3 -m json.tool` —90 only `metadata.apps.<slug>` changed; `overall_default_mentor` and the91 `auth_web_*` blocks are intact.923. A non-admin's save fails with a toast, not a crash.9394## Platform data9596| Hook / call | Purpose |97|---|---|98| `useGetTenantMetadataQuery([{ org }])` | the object (public) |99| `useUpdateTenantMetadataMutation()` → `([{ org, requestBody: { metadata } }])` | PUT (replace — always merge first) |100| `useTenantMetadata()` (`web-utils`) | the SDK's cached view of the same object |101| `GET/PUT https://api.<domain>/dm/api/core/orgs/{org}/metadata/` | REST |102103REST reference: [iblai-api-org](https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/skills/organizations/iblai-api-org/SKILL.md).104105## Related skills106107- `/iblai-vibe-user-metadata` — per-user twin108- `/iblai-vibe-account`, `/iblai-vibe-admin` — where to mount the form109- `/iblai-vibe-auth` — the sign-in page branding keys