Documentation
LIVON
The real-time runtime with API sync for full-stack systems
Realtime API interfaces that stay in sync. Type-safe, validated payloads across frontend and backend. Generated client APIs with JSDoc and sync workflow.
Livon uses one schema to drive backend services, realtime publish/subscribe flows, and generated frontend APIs - keeping data shape, validation, and API sync aligned across your system.
Package badges
@livon/runtime:@livon/schema:@livon/client:@livon/client-ws-transport:@livon/node-ws-transport:@livon/dlq-module:@livon/config:@livon/cli:
What problem does LIVON solve?
Most teams duplicate the same interface definitions across:
- transport payloads
- runtime logic
- operation interfaces
- publish/subscribe event payloads
- generated client types and docs
That slows delivery, lets invalid data slip into runtime paths, and makes docs stale.
Why this matters
Data mismatches usually appear late, when multiple teams are already blocked. LIVON runs these checks when data moves between systems and keeps handlers validated-by-default.
Who should care
- Engineers building frontend apps, backend services, and realtime features.
- Engineering managers who need predictable cross-team delivery.
Client sync is required for generated client usage
If your client runtime uses the generated api module from @livon/client, @livon/cli sync is a required step.
Without sync, the generated client API file is missing or outdated, and the client cannot stay aligned with the server interface.
Fast path
- Mount server schema with explain enabled:
schemaModule(serverSchema, {explain: true});
serverSchema is the direct output of api(...) or composeApi(...).
No additional schema-module input wrapper is required.
- Run sync with your app command:
livon \
--endpoint ws://127.0.0.1:3002/ws \
--out src/generated/api.ts \
--poll 2000 \
-- pnpm dev
In linked mode, LIVON uses kill-all semantics: if either process exits, both stop.
- Mount client runtime with generated module:
runtime(clientWsTransport({url: 'ws://127.0.0.1:3002/ws'}), api);
Parameters in this flow
schemaModule(serverSchema, {explain}):
serverSchema(Api | ComposedApi): server API schema bundle fromapi(...)orcomposeApi(...).explain(boolean): enables explain metadata endpoint for sync.
livon --endpoint ... --out ... --poll ... -- <command>:
--endpoint(string): explain source endpoint.--out(string): generated client module path.--poll(number): sync interval in milliseconds.--(delimiter): separates LIVON flags from the linked command.<command>(string): starts your app process after sync starts.
One schema interface, full lifecycle
This example is intentionally minimal: it uses one simple and composition to extend input with an id.
import {
and,
api,
object,
operation,
string,
subscription,
} from '@livon/schema';
import {runtime} from '@livon/runtime';
import {schemaModule} from '@livon/schema';
const MessageInput = object({
name: 'MessageInput',
shape: {
author: string().min(2),
text: string().min(1),
},
doc: {
summary: 'Message payload',
example: {author: 'Alice', text: 'Hello'},
},
});
const WithId = object({
name: 'WithId',
shape: {
id: string(),
},
});
const MessageWithId = and({
left: MessageInput,
right: WithId,
});
const sendMessage = operation({
input: MessageInput,
output: MessageWithId,
exec: async (input) => ({...input, id: 'msg-1'}),
publish: {
onMessage: (output) => output,
},
});
const ChatApi = api({
operations: {sendMessage},
subscriptions: {onMessage: subscription({payload: MessageWithId})},
});
export const serverSchema = ChatApi;
runtime(schemaModule(serverSchema, {explain: true}));
const incomingInput: unknown = {author: 'Alice', text: 'Hello', id: 'msg-1'};
const parsed = MessageWithId.parse(incomingInput);
const typed = MessageWithId.typed({
author: 'Alice',
text: 'Hello',
id: 'msg-1',
});
// Generated client usage
// await api.sendMessage({ author: 'Alice', text: 'Hello' });
// api({ onMessage: (payload) => payload.id });
Parameters in this example
object({...}):
name(string): schema identifier.shape(Record<string, Schema>): field schema map.doc(SchemaDoc, optional): summary/example metadata used by generated JSDoc.
and({...}):
left(Schema): base schema.right(Schema): extension schema.name(string, optional): explicit composed type name.
operation({...}):
input(Schema): request schema for incoming data.output(Schema): response schema before it is sent.exec((input, ctx) => result): operation logic receiving validated input.publish(Record<string, (output) => payload>): publish mapping from operation output to subscription payload.
MessageWithId.parse(incomingInput):
incomingInput(unknown): untrusted incoming data to validate at runtime.
MessageWithId.typed(value):
value(MessageWithIdshape): compile-time aligned value still checked against runtime constraints.
Generated JSDoc output (generator format)
/**
* Operation: sendMessage.
* Constraints: publish=["onMessage"], request="MessageInput", response="MessageWithId".
* Output type: MessageWithId.
* Input type: MessageInput.
* @param input - MessageInput request payload.
* See {@link MessageInput}.
* @returns MessageWithId operation result.
* See {@link MessageWithId}.
* Publishes events: onMessage.
* @example
* await client.sendMessage({ author: "Alice", text: "Hello" })
* @example
* sendMessage({ author: "Alice", text: "Hello" }: MessageInput): MessageWithId
*/
sendMessage(input: MessageInput): Promise<MessageWithId>;
/**
* Subscription callback for "onMessage".
* Output type: MessageWithId.
* @param payload - MessageWithId payload emitted for "onMessage".
* @param ctx - ClientHandlerContext runtime metadata and room context.
* See {@link MessageWithId} and {@link ClientHandlerContext}.
* @example
* api({ onMessage: (payload) => payload.id });
*/
onMessage?(payload: MessageWithId, ctx: ClientHandlerContext): void;
Core Concepts
- Why Livon Exists
- Validated by Default
- parse vs typed
- Backend / Frontend Symmetry
- SchemaDoc & Generated JSDoc
- How Livon Differs
- When Not to Use Livon
Next sections
- Guides: onboarding and role-focused guidance.
- Technical: runtime architecture and event flow.
- Packages: package-level usage details and schema API references.
- Contribution: governance, quality gates, and contributor workflows.