Support room presence
This example models a support conversation. A room stores members, typing state, assignment metadata, and message history.
Configure the app
Section titled “Configure the app”import { backend } from "@layeron/core"import { realtime } from "@layeron/modules"
const app = backend()const live = realtime({ name: "support", presenceTtlSeconds: 45,})app.use(live)Set room metadata
Section titled “Set room metadata”app.post("/support/:ticketId/metadata", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const ticketId = pathSegments[2] const body = await request.json()
return await live.room(`ticket_${ticketId}`).metadata({ metadata: { ticketId: ticketId, priority: body.priority, assignedAgentId: body.assignedAgentId, status: body.status, }, })})Join as an agent or customer
Section titled “Join as an agent or customer”app.post("/support/:ticketId/join", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const ticketId = pathSegments[2] const body = await request.json()
return await live.room(`ticket_${ticketId}`).join({ metadata: { role: body.role, }, presence: { status: "online", typing: false, }, })})Update typing state
Section titled “Update typing state”app.post("/support/:ticketId/typing", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const ticketId = pathSegments[2] const body = await request.json()
return await live.room(`ticket_${ticketId}`).presence({ presence: { status: "online", typing: Boolean(body.typing), }, })})List active participants
Section titled “List active participants”app.get("/support/:ticketId/members", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const ticketId = pathSegments[2] const members = await live.room(`ticket_${ticketId}`).members({ limit: 25, })
return Response.json({ members })})Close the support room
Section titled “Close the support room”app.post("/support/:ticketId/close", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const ticketId = pathSegments[2] return await live.room(`ticket_${ticketId}`).destroy({ deleteHistory: false, deleteSnapshots: false, })})Keep history when support transcripts must remain available after the room is closed.