FlatpageDocs

GitHub Actions

Publish a build to the same link on every push.

Build your site, zip the output and replace the site's content. The link stays the same, so a review link or a QR code always shows the latest build.

Add the key as a secret

Create a key in Settings named github-actions. In your repository, open Settings → Secrets and variables → Actions and add it as FLATPAGE_API_KEY.

Publish the site once

Publish the first version by hand (dashboard or curl) with the link name you want, for example acme-docs. The workflow then updates it.

Add the workflow

.github/workflows/flatpage.yml
name: Publish to Flatpage
on:
  push:
    branches: [main]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci && npm run build

      - name: Zip the build
        run: cd dist && zip -qr ../site.zip .

      - name: Publish
        env:
          FLATPAGE_API_KEY: ${{ secrets.FLATPAGE_API_KEY }}
        run: |
          curl -sS --fail-with-body -X PUT "https://flatpage.app/v1/sites/acme-docs" \
            -H "Authorization: Bearer $FLATPAGE_API_KEY" \
            -H "Content-Type: application/zip" \
            --data-binary @site.zip | tee result.json
          echo "Published: $(jq -r '.site.url // "still processing"' result.json)"

--fail-with-body makes the step fail on an error and prints the message. Change dist to your build folder (out for Next.js static export, build for Create React App, _site for Jekyll).

Publish each pull request to its own site with a link name like acme-docs-pr-42: POST /v1/sites?linkName=acme-docs-pr-42 the first time (a 409 means it exists), then PUT /v1/sites/acme-docs-pr-42. Delete it when the pull request closes. Mind your plan's site limit.