Skip to content
Get started

zel deploy

Build and put it online, on a CDN or a container host.

terminal
zel deploy netlify
zel deploy fly --tag v2.1.0
zel deploy netlify ./docs --site acme-docs

The provider decides the artefact

This was the missing piece in an earlier draft, which listed providers with no explanation of what got built or where the content came from.

ProviderBuildsBecause
netlifystaticHosts files
cloudflarestaticHosts files
ghpagesstaticHosts files
s3staticHosts files
vercelstaticVercel can run Next.js, but a Zellij site has nothing to run
flyimageRuns containers
railwayimageRuns containers

You do not pass --target. A CDN cannot run a container and a container host has nothing to do with a folder of HTML, so the provider settles it. Passing --target anyway is an error naming the conflict, rather than a silent override.

Where the content comes from

The same resolution every command uses, and the optional [dir] argument:

terminal
zel deploy netlify              # resolved: zel.toml, then ./content, then here
zel deploy netlify ./docs       # this folder

See how a command finds your content. For a repository where the answer is always the same, put it in zel.toml once:

zel.toml
content = "docs/external"

[deploy]
provider = "netlify"
site = "acme-docs"

Then the command is zel deploy.

What it does

  1. Checks

    zel check against the resolved content folder. A broken internal link stops the deploy here rather than shipping a 404.

  2. Builds

    zel build with the target the provider requires.

  3. Authenticates

    Reads the provider's own credential, from the environment or its CLI's stored login. zel never asks you for a token and never stores one.

  4. Uploads

    The folder, or the image followed by a release on the platform.

  5. Prints the URL

    And the deploy id, so it can be rolled back with the provider's own tooling.

$ zel deploy netlify
✓ Content valid — 34 pages, 2 guides
✓ Built static — 34 routes, 4.1 MB
✓ Uploaded to acme-docs
  https://acme-docs.netlify.app
  deploy 66f2c1a8e5b40a0009c2d1e4

Credentials

Read from the environment. Nothing is written to disk by zel.

ProviderReads
netlifyNETLIFY_AUTH_TOKEN, NETLIFY_SITE_ID
cloudflareCLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID
vercelVERCEL_TOKEN
ghpagesGITHUB_TOKEN, or the local git remote
s3The AWS SDK's usual chain
flyFLY_API_TOKEN
railwayRAILWAY_TOKEN

If a credential is missing, the command says which variable and stops before building. Discovering a missing token after a four-minute build is a waste of four minutes.

What it deliberately will not do for you

A reasonable question: since zel deploy netlify knows it needs a Netlify project, why not log you in and create one?

Logging in — no. netlify login is an OAuth flow that opens a browser and waits. Reimplementing it means either a worse version of somebody else's authentication, or asking you to paste a token into a prompt — and a tool that asks for credentials is a tool you have to trust with them. Reading what the provider's own CLI already stored costs nothing and requires no such trust.

Creating a project — not silently. netlify sites:create claims a name on somebody's account and is not obviously reversible. A deploy command that quietly creates infrastructure is one typo away from a second project nobody meant to make, on the wrong account, with a name now taken.

Exporting a token into your shell — never. zel reads credentials and does not write them, anywhere. A tool that edits your environment or your shell profile is doing something you cannot see and did not ask for.

Which leaves one command to run once, by hand, per site:

terminal
netlify login
netlify sites:create --name acme-docs

And then zel deploy netlify for the rest of the project's life.

Options

<provider>Required. One of the table above
[dir]The content folderResolved
--site <name>The site or project on the providerfrom zel.toml
--tag <name:version>Image tag — container providers only<site-name>:latest
--message <text>Deploy message, where the provider has onethe git subject
--previewA preview deploy rather than productionoff
--dry-runBuild and report, upload nothingoff

See also

  • zel build — the two things a site can be
  • zel image — when you want the image but not the deploy
  • zel ci — doing this on every push instead of by hand