@bardioc/app-sdk
v1.0.2
Published
SDK for building apps for Bardioc
Downloads
635
Readme
@bardioc/app-sdk
SDK for building apps that run inside Bardioc as isolated iframes.
An app talks to its host only through a typed contract over a MessagePort: it calls host
methods (ui.*, bff.request, idb.*, apps.*), receives host calls (ui.command) and
events (context.changed), and reads streams (events.graph). Every failure is a
BardiocError with a code.
Requirements
- Node.js
>=20.19.0 - TypeScript
>=6.0.0 - For React apps,
reactandreact-domin the consuming project
Quick start
import { AppSdkProvider, useNotify } from '@bardioc/app-sdk/react';
import { createRoot } from 'react-dom/client';
function App() {
const notify = useNotify();
return <button onClick={() => notify('Hello.', 'success')}>Say hello</button>;
}
createRoot(document.getElementById('root')!).render(
<AppSdkProvider>
<App />
</AppSdkProvider>
);Without React:
import { connect } from '@bardioc/app-sdk';
const bardioc = await connect();
const profile = await bardioc.os.profile.get();Exports
| Path | Contents |
| ---------------------------- | ------------------------------------------------------------- |
| @bardioc/app-sdk | connect, Bardioc, BardiocError, manifest, domain types |
| @bardioc/app-sdk/react | AppSdkProvider and hooks |
| @bardioc/app-sdk/protocol | the contract: APP_METHODS, serve, acceptApp — for hosts |
| @bardioc/app-sdk/dev | installDevHost, isDevStandalone, isInsideIframe |
| @bardioc/app-sdk/dev-proxy | startDevAuthProxy for dev servers without the Vite plugin |
| @bardioc/app-sdk/vite | bardiocApp(), bardiocDevAuth() |
| @bardioc/app-sdk/testing | hostConformance: the behaviour every host must share |
API
const bardioc = await connect();
bardioc.context; // { appId, host: 'os' | 'dev', osConfig }
bardioc.onContextChange(context => {});
await bardioc.ui.notify('Saved.', 'success');
await bardioc.ui.setCommands([{ id: 'save', title: 'Save' }]);
await bardioc.ui.setMenu([{ label: 'File', items: [{ type: 'command', commandId: 'save' }] }]);
const off = bardioc.ui.onCommand('save', () => save());
await bardioc.bff.request({ path: '/os/me/profile' }); // any BFF path outside /auth
await bardioc.graph.query('ogit/_type:ogit/Note', { limit: 10 });
await bardioc.os.organization.getStructure();
await bardioc.relay('notes').request({ path: '/items' });
const notes = bardioc.idb('notes');
await notes.put('n1', { title: 'Hi' });
await notes.get('n1'); // { key, value, updatedAt } | null
const end = await bardioc.events.graph({ types: ['ogit/Note'] }, event => {});
end();
await bardioc.apps.list();Scope: a call without scopeId uses the window's instance; scopeId makes the scope required;
scopePolicy: 'none' sends none.
React hooks
useSdk(), useNotify(), useCommandMenu(commands, menu), useActiveTab(tab),
useOsConfig(), useGraphEvents({ types }, handler).
Errors
import { BardiocError } from '@bardioc/app-sdk';
try {
await bardioc.graph.get(id);
} catch (error) {
if (error instanceof BardiocError && error.code === 'not_found') return null;
throw error;
}Codes: invalid, unauthenticated, forbidden, not_found, conflict, rate_limited,
unavailable, timeout, cancelled, protocol, internal. HTTP failures carry status and the
response body as details.
Standalone development
- Set
DEV_SECRETandAPI_BASE_URLin.env. - Install the dev host before rendering, then run
pnpm dev:
import { installDevHost, isDevStandalone } from '@bardioc/app-sdk/dev';
if (isDevStandalone()) installDevHost();The dev host answers the same contract as the Bardioc host: BFF calls go through the dev-auth
proxy (the bardiocDevAuth Vite plugin, or startDevAuthProxy beside angular and nextjs dev
servers — pass its origin as apiBaseUrl), idb lives in this browser's IndexedDB, ui calls
are acknowledged, and apps answer unavailable.
Vite plugin
// vite.config.ts
import { bardiocApp } from '@bardioc/app-sdk/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [react(), bardiocApp({ appName: 'my-app', port: 3005 })],
});Handles dev base path, port config, host session proxy routes, platform fonts, and manifest validation on build.
Platform fonts
The Bardioc platform guarantees a stable font endpoint wherever an app runs — like /api/transport, it is a public contract that will never be renamed or removed. Load it with one line in index.html and do not bundle font packages into your app:
<link rel="stylesheet" href="/fonts/bardioc-fonts.css" />It provides Nunito Sans Variable (normal + italic) and Geist Mono Variable as variable fonts (latin subset), matching the --font-nunito-sans / --font-geist-mono theme variables that @bardioc/ui resolves by default.
- Embedded in the OS the URL resolves same-origin against the host, which serves it with immutable caching — one download shared by the host and every app.
- Standalone dev the
bardiocApp()plugin serves the same files from assets shipped inside this package (dev server only — they are never added to your bundle). This applies to Vite-based apps; the angular and nextjs templates run their own dev servers, where the link is a harmless 404 standalone and resolves normally embedded in the OS.
New apps scaffolded with create-bardioc-app include the <link> already.
App manifest
Every app must include public/app-manifest.json:
{
"manifestVersion": 2,
"id": "my-app",
"name": "My App",
"version": "1.0.0"
}The Vite plugin validates this automatically and fails the build when the manifest is missing or invalid.
Window
Optionally control how the OS frames the app via a window block:
{
"manifestVersion": 2,
"id": "my-app",
"name": "My App",
"version": "1.0.0",
"window": {
"size": "md",
"resizable": true
}
}size picks a tier (default md):
| Tier | Size (w × h) | Min (w × h) |
| ---- | ------------ | ----------- |
| xs | 480 × 320 | 360 × 280 |
| sm | 640 × 480 | 480 × 320 |
| md | 800 × 600 | 480 × 320 |
| lg | 1024 × 800 | 640 × 480 |
| xl | 1280 × 800 | 800 × 600 |
Instead of a tier, size may be a custom dimensions object — { width, height } (px), with optional minWidth/minHeight (each defaults to a floor when omitted). Custom dimensions are literal, so orientation does not swap them:
{
"window": { "size": { "width": 720, "height": 540, "minWidth": 400, "minHeight": 300 } }
}Other flags (all optional booleans): canHaveMultipleWindows, isInstanceAware, resizable, maximizable, minimizable, customScroll, centered, isHeaderless.
Support
For support, contact [email protected].
License
MIT.
Copyright (c) 2026 ALMATO AG. All rights reserved.
This is an internal library for ALMATO AG.
