Areca Docs

Building during Go live

What your website build must do when Areca deploys it on Go live, including the snapshot build argument, the pull step, the Dockerfile and the health check.

When an editor selects Go live, Areca creates an immutable publication, starts a build of your website, deploys the result and checks it before the release counts as live. Your site needs to cooperate with this in three places: the build must pull the publication it is given, the Docker build must rebuild when the publication changes, and the running site must report which publication it serves at a health URL.

This page is for the developer who owns the site's Dockerfile and health route. For the operator side, including how the deployment target is connected in the CMS, see Deployment targets.

What Areca sends to the build

For a Dokploy application, Areca's Dokploy integration sets these values before each deploy. For a Cloudflare project, see Cloudflare builds.

SettingKindSet by ArecaYour site uses it for
ARECA_CMS_URLBuild argumentNo, you set it onceTelling areca pull where the CMS is
ARECA_SNAPSHOT_IDBuild argumentYes, on every deployChanging the Docker layer that pulls content, so Docker never reuses an older pull
ARECA_SITE_TOKENBuildKit secretNo, you set it onceAuthenticating areca pull during the build
ARECA_SITE_TOKEN and ARECA_CMS_URLRuntime environmentNo, you set it onceOnly needed if the running site serves draft previews

ARECA_SNAPSHOT_ID holds the publication ID. areca pull reads it and pulls exactly that publication. It also changes the Docker build input, so a rebuild cannot reuse a cached pull from an earlier publication. Your Dockerfile must declare it as an ARG, as shown below. Cloudflare builds use the same ID, but as a build variable, and they need no Dockerfile.

Keep the site token out of build arguments

Build arguments and ENV lines are stored in the image history, so anyone with the image can read them. Pass ARECA_SITE_TOKEN as a BuildKit secret only. Do not declare it with ARG or ENV in the Dockerfile.

What the pull receives

areca pull calls the CMS endpoint GET /api/sites/snapshot/current with your site token. If ARECA_SNAPSHOT_ID is set, areca pull also sends it as the publicationId parameter. The CMS decides which publication to return:

  • With a publicationId, it returns that publication, whatever its status.
  • Without one, it returns the live publication. For a site in Demo mode, it returns the demo publication. A release that is still deploying is never returned.

A Go-live build receives the release being built because the build is pinned to it by ARECA_SNAPSHOT_ID, not because that release is the one deploying. If there is no publication to return, the pull fails. An ordinary pull fails with No publication exists for this site, so publish content in the CMS first.

The pull writes manifest.json (which holds the publicationId) and one JSON file per collection into the directory you give it. The demo site uses src/generated/content.

The Dockerfile

The example below is a generic Node site built with pnpm, using Nitro output as the demo does. Adjust the paths and the build command to your project. The order matters:

  1. Install dependencies first, so that layer is cached.
  2. Declare ARECA_SNAPSHOT_ID after installing and before the pull. A changed value invalidates only the pull and the build after it.
  3. Mount the site token as a secret for the pull step only.
Dockerfile
FROM node:24-alpine AS deps
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

FROM deps AS build
ARG ARECA_CMS_URL
ENV ARECA_CMS_URL=$ARECA_CMS_URL
COPY . .
# Changing this value rebuilds the layers below. Areca sets it to the publication ID.
ARG ARECA_SNAPSHOT_ID=
RUN --mount=type=secret,id=ARECA_SITE_TOKEN,required=true \
    ARECA_SITE_TOKEN="$(cat /run/secrets/ARECA_SITE_TOKEN)" \
    pnpm exec areca pull --out src/generated/content \
    && pnpm build

FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
COPY --from=build /app/.output ./.output
COPY --from=build /app/src/generated ./src/generated
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]

Things to check in your own Dockerfile:

  • areca must be installed in the project, so pnpm exec areca finds it. The SDK package provides the areca command.
  • The runner stage does not inherit ENV from the build stage. Copy only what the server needs.
  • If you serve previews, the runner stage needs ARECA_CMS_URL and ARECA_SITE_TOKEN at runtime. Set them as runtime environment variables in the deployment, not as build arguments.
  • To test a build by hand, pass any value: docker build --build-arg ARECA_SNAPSHOT_ID=test-1 --build-arg ARECA_CMS_URL=https://cms.example.com --secret id=ARECA_SITE_TOKEN,env=ARECA_SITE_TOKEN .

The site serves the snapshot it built. Visitor requests do not call the CMS.

The health URL

Production sites must have a health check URL. Areca requests it after the deploy finishes, and the release counts as live only when the response matches the publication. Demo sites skip the deploy and the health check. The health check requires:

  • An HTTP status of 200.
  • A JSON body with a publicationId equal to the publication that was deployed.
{ "ok": true, "publicationId": "the-publication-id" }

Areca polls the URL every 5 seconds for up to 2 minutes. If the response never matches, the Go-live job fails with Health check failed.

The site must return the publication ID from the content it was built with, not from anything else. The demo reads it from the pulled manifest:

src/routes/api/health.ts
import { createFileRoute } from '@tanstack/react-router'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'

export const Route = createFileRoute('/api/health')({
  server: {
    handlers: {
      GET: () => {
        try {
          const manifest = JSON.parse(
            readFileSync(join(process.cwd(), 'src/generated/content/manifest.json'), 'utf8'),
          )
          return Response.json({ ok: true, publicationId: manifest.publicationId })
        } catch {
          return Response.json({ ok: false, error: 'Content manifest missing' }, { status: 503 })
        }
      },
    },
  },
})

Keep the route public, and do not require a login or a token for it. Do not return content or the site token from it.

Set the URL in the CMS, on the Deployment tab of the site settings, in the Health check URL field. The field is required in Production mode, and Go live is blocked until it is set. Use an address the CMS can reach. For the rules on HTTP and private addresses, see Deployment targets.

Cloudflare builds

A site that deploys to a Cloudflare Pages project or a Worker with Workers Builds needs no Dockerfile. Cloudflare builds the site from your repository, so the build command must do the pull itself.

  • Build command. Run areca pull before the site is built, for example areca pull && <your build>, or in a prebuild script. areca must be installed in the project, so the command can find it.
  • Build variables. Set ARECA_CMS_URL (the CMS address the build can reach) and ARECA_SITE_TOKEN (the site token, stored as a secret) on the project. For Pages, use Settings › Variables and Secrets for the production environment. For a Worker, use Settings › Builds › Variables and secrets, as build variables and not runtime variables. Areca does not set these two values.
  • ARECA_SNAPSHOT_ID. Areca sets this build variable before each deploy, to the publication ID of the release. Do not set it yourself. It stays set after the release, so a build that Cloudflare starts from a git push pulls the same release until the next go-live.
  • Health route. The site must serve its health route from the build, as described above. A route, or a static /api/health JSON file generated at build time, both work, as long as the JSON contains the publication ID from the pulled manifest.

For the setup in Cloudflare and the CMS, see Cloudflare.

Troubleshooting

SymptomLikely cause
The deploy finishes quickly, but the site still shows older contentDocker reused the pull layer. Check that ARG ARECA_SNAPSHOT_ID comes after the install step and before the pull.
No publication exists for this siteAn ordinary pull found no live or demo publication. Publish in the CMS, then retry.
Failed to fetch snapshot (404): No publication existsThe build's ARECA_SNAPSHOT_ID is not a publication of this site. Check the build argument or variable.
Health check failedThe URL does not return 200, or its publicationId does not match. Open the URL yourself and compare the value with the release in the CMS.
The build cannot read the tokenThe secret is missing from the build configuration, or the Dockerfile's --mount id does not match. The id is ARECA_SITE_TOKEN.

On this page