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.
| Setting | Kind | Set by Areca | Your site uses it for |
|---|---|---|---|
ARECA_CMS_URL | Build argument | No, you set it once | Telling areca pull where the CMS is |
ARECA_SNAPSHOT_ID | Build argument | Yes, on every deploy | Changing the Docker layer that pulls content, so Docker never reuses an older pull |
ARECA_SITE_TOKEN | BuildKit secret | No, you set it once | Authenticating areca pull during the build |
ARECA_SITE_TOKEN and ARECA_CMS_URL | Runtime environment | No, you set it once | Only 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:
- Install dependencies first, so that layer is cached.
- Declare
ARECA_SNAPSHOT_IDafter installing and before the pull. A changed value invalidates only the pull and the build after it. - Mount the site token as a secret for the pull step only.
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:
arecamust be installed in the project, sopnpm exec arecafinds it. The SDK package provides thearecacommand.- The runner stage does not inherit
ENVfrom the build stage. Copy only what the server needs. - If you serve previews, the runner stage needs
ARECA_CMS_URLandARECA_SITE_TOKENat 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
publicationIdequal 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:
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 pullbefore the site is built, for exampleareca pull && <your build>, or in a prebuild script.arecamust be installed in the project, so the command can find it. - Build variables. Set
ARECA_CMS_URL(the CMS address the build can reach) andARECA_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/healthJSON 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
| Symptom | Likely cause |
|---|---|
| The deploy finishes quickly, but the site still shows older content | Docker reused the pull layer. Check that ARG ARECA_SNAPSHOT_ID comes after the install step and before the pull. |
No publication exists for this site | An ordinary pull found no live or demo publication. Publish in the CMS, then retry. |
Failed to fetch snapshot (404): No publication exists | The build's ARECA_SNAPSHOT_ID is not a publication of this site. Check the build argument or variable. |
Health check failed | The 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 token | The secret is missing from the build configuration, or the Dockerfile's --mount id does not match. The id is ARECA_SITE_TOKEN. |
Related
- Deployment targets for connecting a Dokploy application or a Cloudflare project to the CMS.
- Pulling content for the pull command and its output.
- Draft preview for the runtime variables previews need.
- Example site for a complete working build.
Multilingual sites
Show a site's content in several languages with the SDK. Start with Paraglide, then use the same pattern with i18next, next-intl, vue-i18n or Lingui. Covers fallbacks, per-call locales, hreflang and preview.
Example site walkthrough
Tour the demo site in the examples/demo-site folder, from its content schema and pull step to rendered articles, the preview route and the health check.