Preview Deploys

A live environment per pull request: open a PR, get myapp-pr-42.nest.gethatch.eu, merge or close, and it tears itself down.

How it works

Your CI builds the PR and deploys it with the --preview flag — Hatch stores no GitHub credentials:

hatch deploy --preview pr-42

The preview egg is named <app>-pr-42, gets a normal nest subdomain, and repeat deploys update it in place. Add --json for machine-readable output (the URL for your PR comment).

Quota and energy: at most 3 concurrent previews per app (the 4th returns 422), and previews draw from the parent app's energy budget — no free compute multiplication.

GitHub Action recipe

Copy-paste workflow: build, deploy the preview, and comment the URL on the PR (uses your repo's GITHUB_TOKEN; add HATCH_TOKEN as a repo secret):

name: Preview deploy
on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  preview:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - name: Install hatch CLI
        run: curl -fsSL https://gethatch.eu/install | sh
      - name: Deploy preview
        id: deploy
        env:
          HATCH_TOKEN: ${{ secrets.HATCH_TOKEN }}
        run: |
          url=$(hatch deploy --preview "pr-${{ github.event.number }}" --json | jq -r .url)
          echo "url=$url" >> "$GITHUB_OUTPUT"
      - name: Comment preview URL
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `🐣 Preview ready: ${{ steps.deploy.outputs.url }}`
            })

Automatic teardown

Add Hatch's inbound webhook to your repo (Settings → Webhooks): URL https://api.gethatch.eu/webhooks/github/<app>, content type application/json, your per-app secret, event "Pull requests". When the PR is closed or merged, the matching preview is deleted — routes, database, addons, everything.

No webhook? Previews expire anyway after 7 days (TTL refreshed on each preview deploy).

Manage previews

hatch preview list
hatch preview rm pr-42

Previews also show up on the app page in the dashboard with their PR number, URL, status and expiry.

Hatch mascot