React Integration

Add Traverse capabilities to your React app. You do not need to know Rust. The browser adapter handles all capability execution. Your app only needs to make HTTP requests.

v0.7.0 ~20 minutes Node.js 18+ Rust 1.94+
01
Start the adapter

Start the browser adapter

The browser adapter is a local HTTP server. It takes requests from your React app, runs the WASM capability, and returns a structured response. Start it first, before your React dev server.

Terminal 1 — browser adapter
$ cargo run -p traverse-cli -- browser-adapter serve \
--bind 127.0.0.1:4174 \
--bundle ./bundles/expedition
Loading bundle: ./bundles/expedition
plan-expedition v1.0.0 ... ok
Registry ready. 1 capability loaded.
Adapter listening on 127.0.0.1:4174

Leave this running. Open a second terminal for the next step.

02
Working example

Run the React demo

The repo includes a working React demo. Use it to see a complete integration before adding Traverse to your own app.

Terminal 2 — React demo
$ node apps/react-demo/server.mjs
React demo ready at http://localhost:3000

Open http://localhost:3000 in your browser. Submit the expedition form to see a live execution and trace output.

Both processes must be running. The adapter on port 4174 and the React server on port 3000. The demo shows a blank page if the adapter is not up.
03
How it works

How the connection works

Your React app never touches Rust or WASM directly. It talks to the browser adapter over plain HTTP. The adapter owns everything else.

React app → POST /execute → Browser adapter :4174
JSON body: goal, requested_target, caller
Traverse runtime
WASM capability
Browser adapter :4174 → JSON response → React app
status, output, trace_id, events_emitted

The adapter exposes two endpoints: POST /execute for running capabilities and GET /health for liveness checks.

04
Submit a request

Submit a governed request from React

Use any HTTP client. The body is a JSON object with three fields: goal, requested_target, and caller.

useTraverse.js
const executeCapability = async (goal) => { const response = await fetch('http://127.0.0.1:4174/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ goal: goal, requested_target: 'local', caller: 'my-react-app' }) }); if (!response.ok) { throw new Error(`Adapter error: ${response.status}`); } return response.json(); };

The goal is a plain language description. The runtime matches it to the best capability in the loaded bundle. The caller field identifies your app in trace records.

requested_target tells the runtime which placement to prefer. Use local in v0.7.0. Other targets (browser, edge, cloud, ai-pipeline) are specified but not yet fully implemented.
05
Read the response

Reading the response

A successful response is a JSON object. Check status first, then read output.

example response
{ "status": "completed", "trace_id": "trc_7f3a1b", "capability": "plan-expedition@1.0.0", "output": { "plan": "Day 1: Ascent to base camp at 2800m...", "equipment_list": ["crampons", "ice axe", "tent"] }, "events_emitted": ["expedition.planned"], "duration_ms": 143 }
status
completed or error. Always check this before reading output. On error, an error object is present with reason and stage.
trace_id
Unique execution ID. Store it if you want to correlate frontend events with backend traces.
capability
The ID and version of the capability that ran. Useful for logging and debugging.
output
The capability's output payload. Shape is defined by the contract's outputs schema. Will vary by capability.
events_emitted
List of event IDs published during execution. Empty array if none.
duration_ms
Total execution time in milliseconds. Useful for displaying in developer tooling.
06
Streaming

Handling streaming updates

The adapter exposes a server-sent events stream at /events. Subscribe to it to receive execution lifecycle events in real time without polling.

subscribe to event stream
const subscribeToEvents = () => { const source = new EventSource('http://127.0.0.1:4174/events'); source.addEventListener('execution', (event) => { const data = JSON.parse(event.data); // data.trace_id, data.state, data.capability console.log('State transition:', data.state); }); source.addEventListener('error', () => { source.close(); }); return () => source.close(); // cleanup };

Each SSE message includes the trace_id so you can match stream events to the response from /execute. Use this to show a live progress indicator during long-running capabilities.

07
Display trace data

Displaying trace data in your UI

The trace data in the response gives you everything you need to build a developer-facing execution panel. Here is a minimal React component that renders the key fields.

TracePanel.jsx
function TracePanel({ result }) { if (!result) return null; return ( <div className="trace-panel"> <div className="trace-row"> <span>Status</span> <span className={result.status === 'completed' ? 'success' : 'error'}> {result.status} </span> </div> <div className="trace-row"> <span>Capability</span> <span>{result.capability}</span> </div> <div className="trace-row"> <span>Trace ID</span> <code>{result.trace_id}</code> </div> <div className="trace-row"> <span>Duration</span> <span>{result.duration_ms}ms</span> </div> {result.events_emitted.length > 0 && ( <div className="trace-row"> <span>Events</span> <span>{result.events_emitted.join(', ')}</span> </div> )} </div> ); }

Show the trace panel in a collapsible section alongside your main output. It gives developers immediate visibility into what ran, which version, and how long it took.

No Rust required on your side. Your React app is a plain HTTP client. The browser adapter handles registry lookups, constraint evaluation, WASM execution, and event emission. You only deal with JSON.

Next steps

Troubleshooting
Blank page or connection errors? Common fixes for the React demo.
Architecture
Understand what the adapter does internally and what the trace contains.
MCP Setup
Expose the same capabilities to AI agents over the MCP protocol.