Custom Rendering
If you want to keep the MDAN browser runtime while letting your own framework fully own the UI, this is the path to take.
Shared Principle
@mdanai/sdk/webhandles request lifecycle, state updates, and spec-defined behavior- your framework handles the component tree, rendering, form controls, and visual state
In other words: keep the MDAN behavior layer, replace the view layer.
Lifecycle Pattern
Whether you use Vue or React, the recommended pattern is the same:
- create the host once in the component mount lifecycle
- subscribe to current state immediately after creation
- call
host.mount() - unsubscribe and
host.unmount()during teardown
That avoids duplicate subscriptions, stale runtime instances, and memory leaks.
If you want to inspect raw protocol traffic while building a custom UI, you can also enable browser-side debug messages on the host:
const host = createHeadlessHost({
root: document,
debugMessages: true
});
That keeps a browser-visible log of raw Markdown send/receive messages at window.__MDAN_DEBUG__.messages.
Forms and Operations
GEToperations send an empty payloadPOSToperations only submit the inputs declared by the operation- clear the relevant fields after a successful submission
UI should be derived from current runtime state plus local form state, not from a duplicated set of server assumptions.
Vue Example
Reference: examples/vue-starter/app/client.ts
This is the right path if you want Vue to own the component tree and visual system while keeping MDAN behavior underneath.
React Example
Reference: examples/react-starter/app/client.tsx
This is the right path if you want React to own state projection and interaction components while keeping the same MDAN runtime.
Using a Third-Party Markdown Renderer
If you do not want to use the built-in Markdown rendering behavior, you can also bring a third-party renderer into this path.
Common choices include:
markedmarkdown-itremark
There are two example shapes for this in the repository:
- examples/vue-starter/app/client.ts
uses
markeddirectly in the Vue client - examples/react-starter/app/client.tsx
uses
markeddirectly in the React client
If you want the server output and the default UI to share the same rendering rules as well, see:
In that setup, the same renderer is typically injected into:
@mdanai/sdk/server@mdanai/sdk/elements
That keeps the server-rendered HTML and the default UI aligned.
Common Pitfalls
- recreating the host on every render
- forgetting to
unmountduring teardown - mutating runtime state objects directly
- submitting form state captured from stale closures