# 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](./reference/cli.md#installing-and-updating) 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](./guides/use-with-an-existing-app.md)
or ask [your coding agent](./guides/use-with-a-coding-agent.md) to set up its World.

## 1. Save the app

Save `package.json`:

```json file=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:

```text file=.env.example
STRIPE_SECRET_KEY=
```

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

```js file=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

```bash
npm install
```

This example deliberately substitutes Stripe. For your app, [choose a twin](./guides/choose-a-twin.md)
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:

```bash
npx volter world init --name acme-web
```

```text
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](./reference/coverage.md) 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

```bash
npx volter world up
```

```text
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:

```bash
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](./concepts/worlds.md#sandbox-mode) explains sandbox
mode and its limits.

## 4. Run the app and check its result

```bash
npx volter world run -- node signup.mjs
```

```text
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

```bash
npx volter world log
```

```text
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.

```bash
npx volter world status
```

```text
World acme-web on branch acme-web: running
default data (no remote)
```

For a browser view, [inspect a World](./guides/inspect-a-world.md) 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:

```bash
npx volter world reset
npx volter world clock set 2026-01-15T12:00:00Z
npx volter world log
```

```text
(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](./guides/branch-a-world.md)
explains their lifetime.

```bash
npx volter world run -- node signup.mjs
```

```text
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

```bash
npx volter world down
```

```text
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

- Continue tomorrow with the same records: [resume your World](./guides/resume-a-world.md).
- Bring your own application: [use an existing app](./guides/use-with-an-existing-app.md).
- Choose an implementation or understand its assessment: [choose a twin](./guides/choose-a-twin.md).
- Go from a catalog release to an SDK call: [use a catalog twin](./guides/use-a-catalog-twin.md).
- Open the dashboard: [inspect a World](./guides/inspect-a-world.md).
- Add records: [seed and reset](./guides/seed-and-reset.md).
- Script an answer or failure: [shape the World for a test](./guides/shape-the-world-for-a-test.md).
- Run your own assertions: [run your test suite](./guides/run-your-test-suite.md).
- Run app, database and browser tests: [run a full stack](./guides/run-a-full-stack.md).
- Use an agent: [use World with a coding agent](./guides/use-with-a-coding-agent.md).
- Repeat on pull requests: [use in CI](./guides/use-in-ci.md).
- Collaborate: [share a World](./guides/share-a-world.md).

Shared Worlds, changesets and deployment build on this local workflow. The [model](./concepts/the-model.md)
explains how push moves history between Worlds and deployment performs changes at a real-system root.

<!-- Fenced tutorial executor: packages/cli/src/journeys/tutorial.ts. Execution scope is recorded separately. -->
