Topics & CDC
Project-scoped pub/sub for live UI updates, plus change-data-capture bindings that turn inserts/updates into topics and workflows.
Topics — publish
From a workflow
await ctx.topics.publish("leads.created", {
id: row.id,
email: row.email,
});From the client SDK
await runtime.topics.publish("leads.created", { id, email });HTTP
curl -sS -X POST "$ORIGIN/__appbricx/topics/leads.created/publish" \
-H "Authorization: Bearer $DATA_TOKEN" \
-H "x-appbricx-data-api: 1" \
-H "content-type: application/json" \
-d '{"payload":{"id":"…","email":"a@b.com"}}'Topics — subscribe (SSE)
import { runtime } from "@appbricx/runtime";
import { useEffect, useState } from "react";
function LeadFeed() {
const [events, setEvents] = useState([]);
useEffect(() => {
const unsub = runtime.topics.subscribe("leads.created", (ev) => {
setEvents((prev) => [ev, ...prev]);
// also re-run list_leads
});
return unsub;
}, []);
return /* render events */;
}Under the hood: GET /__appbricx/topics/:name/subscribe streams SSE (event: message + keepalive pings). The API pins the project worker while a subscriber is connected so idle eviction does not drop the bus.
CDC bindings
File: .appbricx/backend/cdc/bindings.json
{
"bindings": [
{
"id": "leads-insert-topic",
"table": "leads",
"ops": ["insert"],
"topic": "leads.created",
"workflow": null
},
{
"id": "leads-insert-notify",
"table": "leads",
"ops": ["insert"],
"topic": null,
"workflow": "on-lead-created"
}
]
}Prefer runtime.upsert_cdc_binding so DB + file stay aligned.
End-to-end example
- UI or REST creates a lead (
runtime.api.createor named query). - Mutation emits CDC → binding publishes
leads.createdand/or enqueues a workflow. - Admin dashboard subscribed via SSE refreshes without a full page reload.
How it works internally
- Named-query / CRUD / data-plane DML calls
emitCdcIfMutation(regex table + op detection). - In-process
appBusfans out to SSE subscribers and CDC handlers on the same API process. - Optional outbox table for durability; Redis multi-node bus is a future path (
appbricx_APP_BUS=inprocesstoday).
Demo tip. For a reliable social clip, publish from the webhook workflow with
ctx.topics.publish and subscribe in the admin UI — you control both ends without depending on CDC regex edge cases.