Developer docs
UI Integration·

UI Integration

The full useNiyase() bridge surface, how audience relates to role, @niyase/plugin-sdk/ui, and rendering across three apps.

You write a plugin's UI in React and access data, notifications, and navigation through the useNiyase() bridge. One plugin = one menu entry in the sidebar (cloud/desktop) or shelf (mobile) — what it shows changes by role.

The full useNiyase() surface

NamespaceUse
niyase.dataCRUD on your own plugin's plg_* tables (Data Model)
niyase.coreRead core data (employees, departments, spaces — Core API)
niyase.connectionsPROVIDER-CLIENT plugins only. List/invite/request/accept/suspend/terminate connections, plus data(connectionId) for connection-scoped CRUD on shared tables
niyase.context{ spaceId, workspaceType, role, audience, locale, theme, plugin } (reactive — subscribers are notified when values change)
niyase.i18nt(key, vars?) / locale. Resolves your plugin's own ja/en messages using context.locale
niyase.navigateTab / route navigation within your own plugin
niyase.toastsuccess / error / info notifications
niyase.paletteRegister / trigger intents in the unified palette (tied to paletteMetadata)
const niyase = useNiyase();

// Subscribe to reactive context (follows theme / language switches)
useEffect(() => niyase.context.subscribe((ctx) => setTheme(ctx.theme)), []);

// Resolve a message from the plugin's own ja/en bundle
const title = niyase.i18n.t("task.title", { count: 3 });

niyase.toast.success("保存しました");
niyase.navigate.toTab("settings");

niyase.connections is cloud-space only. Calling it from a purely local space (desktop PGlite / mobile SQLite with no cloud account) returns the CLOUD_REQUIRED error code. Design PROVIDER-CLIENT plugins together with requiresCloud: true in the manifest (see Manifest).

audience (the display role) and resolveAudience()

Declare per-role display in manifest.audiences[]. A role that isn't in the array gets no side-menu entry and no tabs at all.

audienceIntended userDisplay
executiveExecutives, managersAll management + execution tabs
employeeEmployeesExecution tabs only
customerBusiness partners (the CLIENT side of a PROVIDER-CLIENT pair)Customer-facing tabs only

The value that lands in niyase.context.audience isn't the manifest's defaultRole itself. It's derived by resolveAudience(role, isAdmin) from the plugin_activation.role (PROVIDER / CLIENT / LOCAL) chosen at activation time and whether the current user is an admin:

role === "CLIENT"  → audience = "customer"
isAdmin === true   → audience = "executive"
otherwise          → audience = "employee"

In other words, defaultRole only decides which role a fresh activation starts in — the audience actually shown is resolved per user, every time. Executives see the full "management + execution" tab set by default; if someone wants to see execution tabs only, that's handled by the host's own TabSettings (display settings), not something your plugin needs to build.

UI components

Import niyase's UI components from @niyase/plugin-sdk/ui (the host supplies the real ones).

import {
  Button,
  Input,
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
} from "@niyase/plugin-sdk/ui";

You can also write with plain HTML + Tailwind-like classes. To follow niyase.context.theme (light/dark), it is safer to handle colors with semantic tokens.

The same bundle on three apps

The single bundle you build runs on cloud (Web), desktop (Electron), and mobile (Expo). On all three, your plugin runs in an execution context isolated from the host's own rendering (cloud = a sandboxed iframe, desktop = a <webview>, mobile = a React Native WebView), and every useNiyase() call travels to the host over postMessage. That isolation is a security boundary; the SDK absorbs the transport differences, so your plugin code stays identical across all three.

Your plugin's nav entry (audiences[].nav) shows up, based on the category you declared, inside the section-nav column on cloud/desktop or inside the mobile shelf (the left-hand, two-tier overlay drawer). There's no dedicated app bar or hamburger menu — all three apps have retired those. The page body itself renders inside the host's standard tab layout.

Check the look locally

niyase-plugin dev

It renders for real inside the generic shell, and you can check it while switching role, space type, theme, and language in the DevBar (see Setup).