Skip to content

Content Deploy / CDN

View .md

Content Deploy turns a project’s translations into JSON files at predictable URLs on Cloudflare’s edge. Enable it under Settings → Content Deploy; the endpoint URL appears on the same page with a copy button once it is enabled and saved.

https://cdn.comvi.io/<project-token>/<language>.json # default namespace
https://cdn.comvi.io/<project-token>/<namespace>/<language>.json # any other namespace
https://cdn.comvi.io/abc123/en.json # default namespace, English
https://cdn.comvi.io/abc123/checkout/fr.json # checkout namespace, French
https://cdn.comvi.io/abc123/emails/pt-BR.json # emails namespace, Brazilian Portuguese

The token is project-scoped and generated for you. Each file is named after the canonical BCP-47 code the project stores, and capitalization matters: pt-BR, not pt-br. An underscored or lowercase spelling such as pt_BR.json is a temporary alias; request the canonical name.

Each file is a flat JSON map from key to value, served compact with Content-Type: application/json, and no authentication: anyone with the URL can read the bundle. Treat the token as a secret if the translations themselves are sensitive.

https://cdn.comvi.io/abc123/en.json
{
"greeting": "Hello, {name}!",
"nav.home": "Home",
"nav.settings": "Settings"
}

Settings → Content Deploy controls what is deployed:

Setting Effect
Content Deploy Master switch. Off means nothing is deployed and no endpoint URL exists
Locales Subset of project locales to include. An unticked locale is not deployed at all
Namespaces Subset of namespaces to include
Filter by Status Which statuses to include: Translated, Needs Review, Not Translated. Empty by default, and empty deploys every status

A project has exactly one live configuration; one project cannot serve two endpoints with different filters. The dashboard deploys plain JSON; the REST API’s cdnSettings.format also accepts i18next-v4 (Projects API).

Mode Trigger Delay
Automatic Any translation edit, import or status change 5 s after the last edit, capped at 1 min from the first edit in a burst
Manual Deploy Now next to the CDN endpoint Immediate

Every new edit pushes the scheduled deploy forward by 5 seconds, up to a ceiling of 1 minute, so a burst of edits becomes one job and a long editing session cannot starve the deploy. Deploy Now while an automatic deploy is pending cancels the pending job and runs immediately. Only one deploy runs per project at a time; a manual deploy is ignored while another is in flight.

sequenceDiagram
  participant U as User
  participant P as Platform API
  participant S as R2 Storage
  participant C as CDN Edge
  participant D as Dashboard

  U->>P: Click Deploy Now
  Note over P: Build per-namespace per-language bundles
  P->>S: Upload bundles
  P->>C: Purge cache keys
  P->>D: Send deploy status update
  P-->>U: Deploy complete
A deploy builds one file per selected (language, namespace), uploads to R2, deletes files that left the snapshot, purges the edge cache for every affected URL, and updates the deploy record.

A deploy usually finishes in a few seconds. Its result is recorded on the Content Deploy page and through the REST API: success, partial (some files failed under the threshold, or the build produced warnings such as an ICU message that could not be converted), or failed, with the files uploaded, any warnings and the error message. The last deploy timestamp and result are stored on the project.

Cache-Control: public, max-age=30, must-revalidate, stale-if-error=604800

A deploy purges every file it touches at the edge, so the next request gets the fresh bundle. A browser copy is at most 30 seconds stale and can be served for up to a week if the origin is unreachable. The edge holds a copy for up to 24 hours, which is why the purge, not the max-age, delivers a change within seconds. A browser cache and any CDN of your own are untouched by the purge.

If a read looks stale: confirm Content Deploy is enabled, the locale and namespace are ticked, the value’s status matches the filter, and bypass your own client cache.

A deploy with more than 5% of its files failing is abandoned after the upload pass. The files that uploaded are already live, the rest are not, so the edge holds a mix of old and new bundles until the next successful deploy. Transient R2 errors are the usual cause, and a second deploy clears them; format-conversion errors need the source values fixed first.

There is no rollback button. To undo a bad deploy:

  1. Revert the offending values with the editor’s history.

  2. Click Deploy Now, or wait for the automatic deploy the edits already scheduled.

Every change stays in history, so the rollback is auditable. For versioned snapshots as a compliance requirement, or for a CDN that must not be readable by anyone holding the URL, contact hello@comvi.io.