Project setup
Run configuration
Verified against Soffi ·
To run your app, Soffi needs three things: the commands that install it, the processes that keep it running, and the port its preview should point at. These live in one file, soffi.toml. Soffi doesn't infer any of this at deploy time, so whatever starts your app has to be stated there.
You usually don't write it
When you create a project, Soffi reads your repository (the lockfile, the package scripts, how the app starts) and writes the first soffi.toml as part of setting the app up. If the first deploy fails, she reads the error, fixes the file, and tries again. When a deploy goes wrong later, Soffi can look at the run configuration from any Workspace.
Soffi runs your app with its own dev server, from source, with hot reload. That is how an edit made in a Workspace reaches the preview a moment later, so the run configuration should start the dev server rather than a production build.
Where it lives
A Project's soffi.toml comes from one of two places:
- Your repository. A
soffi.tomlat the root of the repository always wins. Edit it there and the next deploy picks it up. - The Project. If the repository has none, Soffi uses the copy stored on the Project. This is what lets an app run in Soffi before anyone commits a file.
To see which one is in use, open the Project from Projects in the left rail, go to Configure, and choose the soffi.toml tab. When the repository has its own file, the tab shows it read-only. Otherwise Admins can edit the stored copy there and click Save run configuration; an invalid file is rejected with the reason. Editors see it read-only.
What goes in it
A minimal file names the project, runs one process, and exposes its port:
[project]
name = "my-app"
[setup]
run = [{ cmd = "mise exec -- pnpm install" }]
[[run]]
name = "web"
command = "mise exec -- pnpm dev"
[expose]
port = 3000Node, npm, pnpm, yarn, and similar tools are reached through mise exec --, so prefix those commands with it. Soffi writes the prefix for you; a file you write by hand needs it too.
| Section | What it does |
|---|---|
[project] | name is required. |
[setup] | Commands that run once, the first time the app deploys: installs, migrations, seed data. |
[refresh] | Commands that run on every redeploy after that, and when someone edits a file while the app is running. |
[[run]] | Each entry is one long-running process with a name and a command. Use ready_when to wait for one to be up before the next starts. |
[expose] | The port the preview points at, which a [[run]] process must listen on, plus an optional health check (path, expect_status, marker). |
[[env]] | Environment variables. Mark a key sensitive to keep its value out of the file. See Environment variables and keys. |
Each command can take a timeout in seconds and a dir to run in.
Projects with more than one repository
Every repository in the Project sits in its own folder, and the stored run configuration runs from the folder that holds them all. Give each command the dir of the repository it works on. A [refresh] command with its repository's dir reruns only when that repository is edited, so a change to a design system can rebuild it while the app's dev server picks up the result.