Volter World

Getting started

Run a signup app against a local Stripe twin, using Stripe's real SDK. Create a customer, read it back, check the result, and return to the same starting state for another run.

A twin answers one vendor's API. A World runs the twins you select for your app, with their data, scripted behavior and environment. This walkthrough uses local simulated execution: no Stripe account, real API key or Volter platform account is needed. Your app keeps its SDK.

What you need

Use Node 22.6 or newer and npm for this walkthrough. Installing packages needs registry access. The example pins its CLI, twin and SDK. See installation for supported runtimes and other package managers.

Start in a new, empty directory. Save each file under the filename shown and run commands from that directory. To start directly in an existing app, use manual setup or ask your coding agent to set up its World.

1. Save the app

Save package.json:

package.json
{
  "name": "acme-web",
  "private": true,
  "type": "module",
  "dependencies": { "stripe": "17.7.0" },
  "devDependencies": {
    "@volter/world": "3.0.69",
    "@volter/twin-stripe": "3.0.2"
  }
}

Save .env.example. These names tell World which credentials the app reads; leave values empty:

.env.example
STRIPE_SECRET_KEY=

Save signup.mjs. It creates and retrieves a customer with the same SDK calls used in production:

signup.mjs
import assert from 'node:assert/strict';
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const customer = await stripe.customers.create({ email: 'ada@example.com', name: 'Ada' });
const saved = await stripe.customers.retrieve(customer.id);
assert.equal(saved.email, 'ada@example.com');
assert.equal(saved.name, 'Ada');
console.log(`created ${customer.id}`);
console.log('customer read-back passed');

There is no twin URL or mocked client in the app. The assertion checks stored behavior, rather than just whether a request returned a success status.

2. Install and select the twin

npm install

This example deliberately substitutes Stripe. For your app, choose a twin that serves the operations you need. Catalog vendor names identify APIs; npm package names identify implementations, which may come from different publishers.

Create the World with the locally installed, pinned CLI:

npx volter world init --name acme-web
stripe
COVERED:

Read the detected vendors and their reasons before keeping them. This app names only Stripe's SDK and credential. Finding a twin does not establish support for every Stripe operation; the coverage guide explains the distinction.

init writes .volter/world.json, recording the selected package and version, and prepares fake credentials. Keep real credentials out of the World. Commit the config, project-owned seeds and handlers with package.json and package-lock.json. The generated ignore file keeps running state out of Git.

3. Start the World

npx volter world up
acme-web  1 twin up, story loaded

A fresh branch loads its default data. Ordinary up later resumes retained state; it does not reset data on every start.

Freeze the World clock so vendor timestamps have the same starting instant:

npx volter world clock set 2026-01-15T12:00:00Z

The twin answers selected Stripe requests locally. Routing alone is not a network isolation boundary for arbitrary programs; Worlds explains sandbox mode and its limits.

4. Run the app and check its result

npx volter world run -- node signup.mjs
created cus_twin_1
customer read-back passed

run supplies a fake credential and routes the SDK's normal api.stripe.com requests to the twin. The assertion passed: the created record was visible on the next read. Run your development server or test runner the same way, with its usual command after --.

5. Inspect what happened

npx volter world log
customer.create
event.record

The log records the customer write and the event Stripe records for it. Reads do not add stored mutations. There is no staging or commit step in a World.

npx volter world status
World acme-web on branch acme-web: running
default data (no remote)

For a browser view, inspect a World opens its dashboard and vendor screens. The CLI log and SDK assertions already let you inspect this run.

6. Reset and repeat

The World retains writes between runs. Reset before repeating this example:

npx volter world reset
npx volter world clock set 2026-01-15T12:00:00Z
npx volter world log
(no changes yet)

Reset discards this branch's changes and reloads default data. Set the clock explicitly for each replay. A parent with dependent branches cannot be reset; branching explains their lifetime.

npx volter world run -- node signup.mjs
created cus_twin_1
customer read-back passed

The customer is created from the same starting state and the assertion passes again. This example checks those outcomes; it is not a claim about complete Stripe fidelity.

7. Stop

npx volter world down
Stopped acme-web

down stops compute and retains branch state. reset returns it to default data. down --purge removes retained state when no dependent branch references it.

Choose your next task

Shared Worlds, changesets and deployment build on this local workflow. The model explains how push moves history between Worlds and deployment performs changes at a real-system root.

View Markdown source

On this page