slew docs/deploy/push-to-deploy

Git push-to-deploy

Connect a GitHub repository to a project and slew builds and deploys it for you: push to your branch and the release goes live; open a pull request and the PR gets an expiring preview URL in a comment.

git push
  → webhook → build queued
  → source fetched at your commit
  → install + build in an isolated container
  → output deployed, CDN purged
  → live at https://<project>.slew.cloud

Connect a repository

Console: sign in at app.slew.cloud, open the GitHub page (or a project's Git section), and install the slew GitHub App on the account or organization that owns the repo — you choose which repositories it can see. The console notices the installation by itself (the installer's GitHub identity links it to your slew account); if it ever doesn't, Re-check with GitHub reconciles. Then New project walks through the four things a deploy needs, in order:

  1. Repository — search your installations, most recently pushed first.
  2. Build settings — read from the repo before anything is built, and editable.
  3. Environment variables — added before the first build runs, so a build that needs a key has it. Paste a .env file and they all land at once.
  4. Custom domain — optional; the DNS record you need is on the next screen.

Nothing is created until the last step, so leaving halfway leaves no half-made project behind.

The build settings are filled in from the repository itself — its packageManager field, its lockfile, its dependencies:

Setting Filled in from Meaning
Package manager lockfile / packageManager npm, pnpm, yarn or bun
Install the manager it found Dependency install command
Build your build script Build command; empty if you have none
Output directory the framework it found The output that gets deployed
PR previews on Preview URL per pull request

Change any of them and slew runs exactly what you typed. An empty install or build command means "run nothing" — a repository of plain HTML deploys as it is.

Package managers

npm, pnpm, yarn and bun all work, with nothing to configure. slew reads your packageManager field if you have one and your lockfile otherwise, then installs with that manager — pnpm install --frozen-lockfile for a pnpm-lock.yaml, bun install --frozen-lockfile for a bun.lock, and so on. That happens when you connect the repository, so the commands on the project's Git tab are the commands your builds run; the manager is also the first line of every build log.

Assembled server artifacts (Astro, SvelteKit, Remix) install their production dependencies the same way, so commit the lockfile your manager writes — that is what makes the deployed node_modules match the build.

Two things to know:

  • Yarn's Plug'n'Play mode produces no node_modules at all, so an assembled server can't load anything. Set nodeLinker: node-modules in .yarnrc.yml. Static builds are unaffected.
  • Set the install command yourself and slew runs exactly that, no detection — the escape hatch for monorepos and custom flags.

CLI: the same flow is one command — it opens the install page if needed, waits, and connects:

slew git connect owner/repo --build-cmd "npm run build" --output dist
slew git                 # connected repo + recent builds
slew git build           # rebuild the branch head now
slew git log             # print the latest build's log
slew git log <build-id>  # print a specific build's log

Every push to the branch then deploys automatically. Deploy now in the console (or slew git build) rebuilds on demand, and builds — with their logs — are listed on the project page.

When a build fails, read why from the terminal: slew git log prints the latest build's log (the header goes to stderr, so slew git log > build.log captures just the log). In the console, click a build's push/PR button to expand its log inline.

Pull request previews

With previews enabled, every opened or updated PR is built and published as a temporary share that expires after 7 days, and the build bot comments the URL on the PR. Previews update on every push to the PR.

Branch domains

A custom domain can track a git branch instead of production — a permanent staging URL, the way Vercel does it:

$ slew domains add staging.example.com --branch staging

From then on, every push to staging builds and deploys to staging.example.com, while pushes to your production branch keep deploying to the project's other domains. The branch deployment goes through the same pipeline as production — same build container, same boot health gate for server runtimes — it just never becomes the production deployment.

Details worth knowing:

  • Assigning a branch queues its first build immediately; until that lands the domain serves production, and the console says so.
  • Two domains tracking the same branch share one build per push.
  • Retarget any time: slew domains branch staging.example.com <branch>, or back with slew domains branch staging.example.com production — also in the console's Domains tab.
  • The production branch itself can't be a branch target; that's what the project's other domains already serve.
  • Branch deployments show up in the deployments list with a branch badge, and can be promoted to production with a normal rollback/activate.
  • Environment variables are shared with production — there is no per-branch environment (yet).

How builds run

  • Source is fetched as a tarball at the exact commit via the GitHub App — no deploy keys to manage, private repos included.
  • The build runs in a throwaway container with no privileges: 2 CPUs, 2 GB memory, a 10-minute limit, and all capabilities dropped.
  • Only the output directory is deployed; the deployment records the commit SHA it was built from.
  • A Next.js build with output: 'standalone' is detected automatically and deployed as a server — the output-directory setting is ignored for it. Any other server app deploys by emitting the output contract into the output directory; the framework recipes show how.
  • A failed build changes nothing: the previous deployment stays live.

The CLI keeps working exactly as before — slew deploy and git push-to- deploy coexist on the same project.