Deployment
Ceres is a bunch of static files (HTML, JS, CSS, JSON, images). After building, they get uploaded to Azure Blob Storage and served through the lstatic CDN.
Where Ceres lives
The built files are hosted at:
https://lstatic.refrens.com/ceres/
This is a CDN endpoint that serves static files from Azure Blob Storage. Here is the full path:
Azure Blob Storage ($web/ceres/)
|
v
lstatic CDN (lstatic.refrens.com/ceres/*)
|
v
User's browser
Caching rules
Not all files are cached the same way:
| File type | Caching | Why |
|---|---|---|
.js files | Cached (with content hash or version in filename) | They have unique names, so caching is safe |
.css files | Cached (same reason) | Same, version in filename |
.json files | Not cached (forced no-cache) | Manifests need to update instantly when a new version is deployed |
.html files | Not cached (forced no-cache) | index.html should always be fresh |
This setup means:
- When you deploy a new template version, the manifest.json updates immediately
- Browsers fetch the new manifest, see the new version path, and load the new JS/CSS
- Old JS/CSS files can stay cached forever because they will never be referenced again
The deployment workflow
Deployment is handled by a GitHub Actions workflow at .github/workflows/deployCDN.yml. Here is what it does:
- Triggers on deployment event (not on push, deployment is triggered separately)
- Checks out the code
- Installs Node.js 22 and dependencies (
npm ci) - Builds everything (
npm run build) - Logs into Azure using credentials stored in GitHub secrets
- Uploads
dist/to Azure Blob Storage usingaz storage blob upload-batch - (Optional) Purges the CDN cache if needed
The upload command looks like this:
az storage blob upload-batch \
--account-name $CERES_STORAGE_ACCOUNT \
--auth-mode key \
-d '$web/ceres' \
-s ./dist \
--overwrite
This uploads everything from dist/ into the $web/ceres container in Azure Blob Storage.