Chapter 9: Realtime Rendering

This chapter shows how to render timeline data into the DOM. The pattern is: store structured data on a timeline, derive HTML, then mount it.

Scenario

Imagine a small weather widget. The model or another data source writes a weather object, and the UI updates automatically.

Step 1: Define Object and HTML Timelines

const weather = useTimeline<WeatherData>({ name: 'weather' });

useTimeline<string>({
  name: 'weather-html',
  fill: reactionFrame({
    triggers: { weather },
    compute({ weather }) {
      if (!weather?.value) return '';
      return renderToHtml(weather.value);
    },
  }),
});

The object timeline is the source. The HTML timeline is a derived view.

Step 2: Mount to the DOM

import { DomMountFeature } from '@chronoai/toolkit/dom-mount';

agent.use(DomMountFeature, {
  mounts: [
    {
      timeline: 'weather-html',
      target: '#weather',
      mode: 'html',
    },
  ],
});

When weather-html changes, the target element updates.

Step 3: Write Data

await agent.write('weather', {
  city: 'Shanghai',
  temperature: 26,
  condition: 'Cloudy',
});

The write triggers the derived HTML timeline and then the DOM mount.

DomMountFeature Configuration

Mount Entry

A mount entry usually contains:

FieldMeaning
timelineSource timeline to observe
targetCSS selector or element resolver
modeRender mode, such as text or html

Write Modes

Use text mode for plain strings and HTML mode for trusted rendered HTML.

{ timeline: 'status', target: '#status', mode: 'text' }
{ timeline: 'panel-html', target: '#panel', mode: 'html' }

Multiple Mounts

agent.use(DomMountFeature, {
  mounts: [
    { timeline: 'title', target: '#title', mode: 'text' },
    { timeline: 'body-html', target: '#body', mode: 'html' },
  ],
});

Streaming Updates

If a timeline receives streaming frames, the mounted UI can update as chunks arrive.

Complete Example

const WeatherFeature = defineFeature('weather', () => {
  const weather = useTimeline<WeatherData>({ name: 'weather' });

  useTimeline<string>({
    name: 'weather-html',
    fill: reactionFrame({
      triggers: { weather },
      compute({ weather }) {
        if (!weather?.value) return '<p>No weather data.</p>';
        return `<strong>${weather.value.city}</strong>: ${weather.value.temperature}C`;
      },
    }),
  });
});

agent.use(WeatherFeature);
agent.use(DomMountFeature, {
  mounts: [{ timeline: 'weather-html', target: '#weather', mode: 'html' }],
});

Summary

  • Keep structured data on timelines.
  • Derive presentation strings or HTML through reactions.
  • Mount rendered timelines with DomMountFeature.
  • Streaming frames can update the UI progressively.

Next

Continue with Chapter 10: Streaming.