Server state and reusable TSX components
Documentation for Redweb 0.13.3. Install that exact version when following these examples.
Ordinary TSX expressions read server-owned state and update automatically after an action; no repeated binding names or browser component runtime.
Use the complete realtime recipe for setup, files, and tests.
import { action, page, start, state, type LiveHtmlStartOptions } from 'redweb';
import { runApp } from './run-app';
@page('/', { css: 'app.css', shared: true })
export class CounterPage {
@state() count = 0;
@action()
increment() { this.count += 1; }
render() {
return (
<main class="home">
<h1>A counter owned by the server</h1>
<p>Open this page in two tabs. Either button updates both.</p>
<button rw-click="increment">
Count {this.count}
</button>
</main>
);
}
}
export function createApp(options: LiveHtmlStartOptions = {}) {
return start(CounterPage, { port: Number(process.env.PORT ?? 8181), templateRoot: __dirname, ...options });
}
if (require.main === module) runApp(createApp);Notes and boundaries
- The first response is complete server-rendered HTML.
- Function components handle stateless snippets; decorated classes own state and actions.
- There is no React dependency, virtual DOM, or hydration pass.