Backend / Frontend Symmetry
LIVON keeps backend and frontend composition symmetric so teams can reason with one schema model.
Backend composition
import {and, api, object, operation, string, subscription} from '@livon/schema';
const MessageInput = object({
name: 'MessageInput',
shape: {
author: string(),
text: string(),
},
});
const WithId = object({
name: 'WithId',
shape: {
id: string(),
},
});
const Message = and({
left: MessageInput,
right: WithId,
name: 'Message',
});
const sendMessage = operation({
input: MessageInput,
output: Message,
exec: async (input) => ({...input, id: 'msg-1'}),
publish: {
onMessage: (output) => output,
},
});
export const ChatApi = api({
operations: {sendMessage},
subscriptions: {onMessage: subscription({payload: Message})},
});
Frontend composition
import {api} from './generated/api';
api({
onMessage: (payload) => {
payload.text;
},
});
await api.sendMessage({author: 'alice', text: 'hello'});
Parameters in these examples
publish.onMessage:
output(Infer<typeof Message>): validated operation output mapped to subscription payload.
api({ onMessage }):
onMessage((payload) => void): generated callback with payload type derived from server schema.
api.sendMessage(input):
input(MessageInput): generated operation input type derived from server schema.
Publish to subscription type propagation
The same event name and schema define both sides:
- backend
publish.onMessageemits payload from validated output. - frontend
api({ onMessage })receives the same payload schema.
This is interface symmetry: one deterministic schema source with mirrored execution behavior.
Cognitive impact
- Lower context switching between backend and frontend.
- Fewer translation layers between API and event handling.
- Structural alignment stays visible in code review and debugging.