Quickstart
This is the first static deploy. You need Node.js 20 or newer (for npx) and an email address. Nothing else: no account is created until the CLI opens a browser.
1. A directory with an index.html
Section titled “1. A directory with an index.html”mkdir hello-tori && cd hello-toricat > index.html <<'EOF'<!doctype html><meta charset="utf-8"><title>Hello from Tori</title><h1>Hello from Tori</h1>EOFIf you already have a site that builds to dist/, build/, out/, or _site/ with an index.html inside, use that project instead.
2. Deploy
Section titled “2. Deploy”npx tori.hostIf this machine has never signed in, a browser opens. Sign in (or sign up — same click). The CLI packs the files, uploads them, and waits until the site answers:
✓ live: https://plucky-wren.tori.cloudOpen that URL. You should see the page you just wrote.
The first deploy creates the app and writes tori.json in the current directory:
{ "slug": "plucky-wren"}Keep that file in version control so later deploys update the same app. Commands such as tori logs and tori env read the slug from it.
3. Deploy again
Section titled “3. Deploy again”Edit index.html and run npx tori.host from the same directory. The CLI reuses the slug in tori.json. live means the files of this deploy are the ones the URL serves. There is no separate promote step. Ctrl+C stops watching; it does not cancel an upload that already finished.
What the CLI looks for
Section titled “What the CLI looks for”With no directory argument it uses dist/, build/, out/, or _site/ when one of them contains index.html. Otherwise it runs npm run build and looks again, then ./index.html — unless the directory also looks like a server, in which case it stops rather than publish source; see the table below.
Pass a directory to skip detection:
npx tori.host deploy ./distIf none of those exist, it exits with nothing to deploy and names what it looked for. Build the site first, or pass the directory that holds index.html.
Frameworks
Section titled “Frameworks”Vite, Astro, and similar tools work when you deploy the output directory, not the source tree:
npm run buildnpx tori.host deploy ./distnode_modules and .git at the top of the packed directory are skipped. Do not pack tori.json into the site; the CLI already excludes it.
If it is a server, not a site
Section titled “If it is a server, not a site”A service is a different app kind: a container the zone runs for you. With a Dockerfile at the root, or a server the CLI recognises — Express or Next.js in package.json, Django or FastAPI in requirements.txt, a Go module, a Rails Gemfile and others — npx tori.host builds it on Tori with no flag. When it does not recognise the server, say so and the language is detected:
npx tori.host deploy --serviceWithout a Dockerfile, a server that also holds an index.html is not guessed: the CLI asks at a terminal, and elsewhere stops and prints --service and, when the site is in an output directory of its own, --static, the flag that publishes the files instead.
If you already have an image, nothing is packed — the reference travels, digest-pinned:
npx tori.host deploy --image registry.example.com/acme/api@sha256:<64 hex>The container must listen on port 8080 — or on the port named with --port or "port" in tori.json — and declare a numeric non-root USER. See Deploy a container service and tori deploy.
If something fails
Section titled “If something fails”| What you see | What to do |
|---|---|
| Browser does not open (SSH, CI, no display) | Use the printed https://my.tori.host/cli-auth code, or set TORI_TOKEN in CI. Sign in |
no API token found, and this looks like CI |
Mint a token in the console under Settings → API tokens and export TORI_TOKEN |
nothing to deploy |
Create index.html, run the framework build, or pass ./dist; for a server, npx tori.host deploy --service |
looks like a server and also holds a static site |
Run one of the commands it prints: npx tori.host deploy --service, or --static when the site is built into a directory of its own. Never publish a directory that holds server code or a .env |
it is not published as files unless named |
Its index.html is beside server code. Deploy it as a service, or move the site into a directory of its own; npx tori.host deploy --static . publishes the whole directory, source included |
npm run build failed |
Fix the build, then deploy the output directory explicitly |
| Archive refused before upload | Drop large files; the CLI checks a local size cap, and the server also enforces the plan’s artefact limit |
deploy failed: … |
The server stored a reason (deploys.error). Fix that, then deploy again. Deploy status and recovery |
Download this page as Markdown.