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:
- Repository — search your installations, most recently pushed first.
- Build settings — read from the repo before anything is built, and editable.
- Environment variables — added before the first build runs, so a
build that needs a key has it. Paste a
.envfile and they all land at once. - 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_modulesat all, so an assembled server can't load anything. SetnodeLinker: node-modulesin.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 withslew 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
branchbadge, 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.