@app/backend
The @app/backendpackage is the seam between a generated app’s @app/sdk hooks (useList, useGet, useActions, useAuth, useWorkflows, useNotifications) and the real Appbricx runtime. Every read, mutation, and subscription resolves against your project’s Postgres, real users, and real workflow runs — no mocks, no local storage fallbacks.
createAppbricxBackend() into their <AppRoot>. Reach for this page when you’re writing a custom host, debugging the data seam, or embedding an Appbricx-generated frontend inside your own shell.Installation
pnpm add @app/backendIn the monorepo this is a workspace dependency (@app/backend: workspace:*). It depends on @app/sdk for the type contract and @appbricx/runtime for the transport (baked project key, postMessage in preview, __APPBRICX_DATA_TOKEN discovery, retries, and the /__appbricx/* routes).
Exports
createAppbricxBackend(opts?)— returns aPlatformBackend({ data, auth, workflows }) ready to hand to<AppRoot>.AppbricxBackendOptions— TypeScript interface for the options bag (baseUrl,token,authFetcher).
Basic usage
import { AppRoot } from "@app/sdk";
import { createAppbricxBackend } from "@app/backend";
import { manifest } from "./manifest";
export default function App() {
return (
<AppRoot manifest={manifest} backend={createAppbricxBackend()} />
);
}With no options the backend resolves its base URL from window.location.origin and its bearer token from a globally-injected __APPBRICX_DATA_TOKEN (the runtime waits up to ~2s for it to land, which covers the preview handshake).
Options
interface AppbricxBackendOptions {
baseUrl?: string; // e.g. "https://app.example.com"
token?: string; // bearer token override
authFetcher?: (path, init?) => Promise<Response>; // full fetch override
}baseUrl— override the origin. Useful for SSR, tests, or embedding an app cross-origin.token— pass a bearer token explicitly instead of waiting for the injected global.authFetcher— swap the whole HTTP layer (cookies, headers, credentials). Only the auth & workflow endpoints use this; data reads go through the runtime client.
What each surface does
data
Backs useList, useGet, useActions, and live subscriptions. All routes go through @appbricx/runtimeto your project’s Postgres.
backend.data.list("todos"); // → Row[] (limit 1000)
backend.data.create("todos", { title }); // POST
backend.data.update("todos", id, { done }); // PATCH
backend.data.remove("todos", id); // DELETE
// Live changes over the runtime topic bus:
const off = backend.data.subscribe("todos", (change) => {
// change: { entity, event: "insert" | "update" | "delete", row }
});
off();Each mutation throws on a non-ok response — surface it or let useActions catch it.
auth
Hits /__appbricx/auth/* through the configured fetcher. Sessions are cookie-based (credentials: "include" on the default fetcher), so a successful signInWithEmail also authorizes later data calls.
await backend.auth.currentUser(); // BackendUser | null
await backend.auth.signInWithEmail(email, pw); // BackendUser | null
await backend.auth.signUp({ email, password }); // BackendUser | null
await backend.auth.signOut();The returned BackendUser is normalized: { id, email, name, role }. role falls back to "admin" when the server sends is_admin: true, otherwise "user".
workflows
Triggers workflow runs, lists notifications and past runs, and subscribes to notification pushes. See Workflows for how workflow files are authored and scheduled.
await backend.workflows.trigger("on-lead-created", { email });
const runs = await backend.workflows.listRuns(); // BackendRun[]
const notes = await backend.workflows.listNotifications(); // BackendNotification[]
await backend.workflows.markAllRead();
const off = backend.workflows.subscribeNotifications(() => refresh());
// Fire a webhook exactly like an external caller would:
await backend.workflows.simulateWebhook("/stripe", { type: "invoice.paid" });Config it reads
No environment variables of its own. It only reads what the runtime exposes at boot:
window.__APPBRICX_DATA_TOKEN(or__appbricx_DATA_TOKEN) — bearer token the preview host or generated shell injects.window.location.origin— default base URL whenbaseUrlis unset.
Both are override-able via AppbricxBackendOptions, which is how tests and cross-origin embeds bypass the auto-discovery.
Custom auth fetcher
Wrap the default fetcher when you need extra headers, a proxy, or a different credentials mode:
const backend = createAppbricxBackend({
baseUrl: "https://app.example.com",
authFetcher: async (path, init = {}) => {
const headers = new Headers(init.headers ?? {});
headers.set("x-tenant", currentTenantId());
return fetch(`https://app.example.com${path}`, {
...init,
headers,
credentials: "include",
});
},
});Related
- Workflows — server-side
run(ctx)functions the SDK triggers. - REST API — the HTTP surface under
/__appbricx/*that this SDK wraps. - Named queries — the safer alternative to raw CRUD for anything non-trivial.