Skip to content

Set up the TodoMVC example

The TodoMVC example is a small, complete EvidentSource application: five State Changes that create, rename, complete, delete and clear todos, and two State Views that read them back. This page builds it, publishes it to a database of your own, and runs it.

It takes a few minutes, most of them spent compiling.

  • Rust, with the WebAssembly target: rustup target add wasm32-wasip2
  • git and curl
  • A server: the public Sandbox, or one on your machine.

The Sandbox. Nothing to install. It is shared and public, and its data is purged periodically; read About the Sandbox first.

Terminal window
export EVIDENTSOURCE_URL=https://sandbox.evidentsource.com

Your machine. Run the development image with in-memory storage. Data is lost when the container stops.

Terminal window
docker run -d -p 3000:3000 -p 50051:50051 evidentsource/evidentsource-dev:0.8.38@sha256:16c279e5dee4a1b0e3951067ed871040251266fd1d7404554744b31b04bbbc69 \
server --scheme http --dev --node-id node-1 --writer memory
export EVIDENTSOURCE_URL=http://localhost:3000

--writer matters: a lone server started without it refuses every write.

Database names must be unique on a server. The Sandbox is shared, so include something of your own in the name:

Terminal window
export EVIDENTSOURCE_DATABASE=todomvc-yourname
curl -X POST "$EVIDENTSOURCE_URL/api/v1/db" \
-H 'Content-Type: application/json' \
-d "{\"database_name\": \"$EVIDENTSOURCE_DATABASE\"}"

A new database answers 200 on the pinned local release above and 201 on the current server. A name that is taken answers 409: pick another.

Terminal window
git clone https://github.com/evidentsystems/evidentsource-sdks.git
cd evidentsource-sdks/rust/examples/todomvc
./build_all.sh

This compiles each State Change and State View to a WebAssembly component under target/wasm32-wasip2/release/.

install.sh publishes to $EVIDENTSOURCE_URL and $EVIDENTSOURCE_DATABASE:

Terminal window
./install.sh --all

Answer y to the prompt. Each component uploads with its metadata.json, which names it and, for a State View, says which events it reads. The first publish of each is version 1.

Uploading state change create-todo... ok
…
Uploading state view todo-list... ok

A todo’s id is a UUID you choose.

Terminal window
export TODO_ID=3f0b5a0e-1c2d-4e5f-8a9b-0c1d2e3f4a5b
curl -X POST "$EVIDENTSOURCE_URL/api/v1/db/$EVIDENTSOURCE_DATABASE/latest/state-changes/create-todo/v1" \
-H 'Content-Type: application/json' \
-d "{\"todoId\": \"$TODO_ID\", \"title\": \"Try EvidentSource\", \"effectiveTimestamp\": \"2026-09-17T00:00:00Z\"}"

The reply is the transaction the command committed, with the revision it reached:

{"id":"01a0ad3f-…","database":"todomvc-yourname","revision":"1","timestamp":"…","metadata":{"origin":{"httpStateChange":{"name":"create-todo","version":"1"}}}}
Terminal window
curl -L "$EVIDENTSOURCE_URL/api/v1/db/$EVIDENTSOURCE_DATABASE/latest/state-views/todo-list/v1"
{"todos":[{"id":"3f0b5a0e-1c2d-4e5f-8a9b-0c1d2e3f4a5b","title":"Try EvidentSource","completed":false,"createdAt":"2026-09-17T00:00:00Z"}]}

latest redirects to the database’s current revision, so pass -L.

single-todo reads one todo. Its events are selected by subject, bound with a query parameter:

Terminal window
curl -L "$EVIDENTSOURCE_URL/api/v1/db/$EVIDENTSOURCE_DATABASE/latest/state-views/single-todo/v1?subject.todo_id=$TODO_ID"
Terminal window
curl -X POST "$EVIDENTSOURCE_URL/api/v1/db/$EVIDENTSOURCE_DATABASE/latest/state-changes/toggle-todo/v1" \
-H 'Content-Type: application/json' \
-d "{\"todoId\": \"$TODO_ID\", \"effectiveTimestamp\": \"2026-09-17T00:05:00Z\"}"

Read single-todo again, and it shows "completed": true, with completedAt taken from the command’s effectiveTimestamp.

State ChangeBody
create-todotodoId, title, effectiveTimestamp
rename-todotodoId, title, effectiveTimestamp
toggle-todotodoId, effectiveTimestamp
delete-todotodoId, effectiveTimestamp
clear-completedeffectiveTimestamp
State ViewReadsParameters
todo-listevery event in the todos streamnone
single-todothe events whose subject is one todosubject.todo_id

Every event is in the todos stream, with the todo’s id as its subject.

  • 400 with validation error: the command was refused. The message says why: an empty title, or a missing field such as effectiveTimestamp.
  • 404 on a command or view: check the database name, and that install.sh published that component.
  • install.sh says a .wasm file is missing: run ./build_all.sh first.
  • Issuing commands and Reading state views explain the two routes you just used.
  • State Changes & State Views explains what the components do.
  • Each language in the SDK repository has the same TodoMVC example, under <language>/examples/todomvc/ (dotnet/examples/TodoMvc/ for .NET). This page follows the Rust one.