Template files and your own templates
This page explains the Quant files in a template repository, what you must do when you copy a template without the dashboard wizard, and how to write a template of your own.
Copy a template by hand
Section titled “Copy a template by hand”When you fork or copy a template on GitHub instead of using the template wizard, nothing in quant/meta.json is applied for you.
- Create the target first: a Quant project (static) or a Quant Cloud application (app). If the app needs a database, create the application with a managed database (the dashboard toggle, or
"database": {"engine": "mysql"}or"postgres"in the API body). - Add the GitHub secrets and variables that the wizard would set (see What happens behind the scenes). Set
QUANT_APPLICATIONto your application name; without it, the app workflow uses the repository name. - On QuantGov, set the
QUANT_BASE_URLvariable tohttps://dash.quantgov.cloud/api/v3(apps), and give the deploy and purge stepsendpoint: https://api.quantgov.cloud/v1(static). - Create what
quant/meta.jsondeclares: secrets on the environment, KV stores (create, link to the project, write the initial values), and project settings such as inline functions. - For an app, check that the build platform matches the architecture (below).
- You can delete
ci.yml. It maintains the template itself. - Push to
main. The init action deploysmainto theproductionenvironment.
Check the copied workflow
Section titled “Check the copied workflow”An app workflow must deploy only into your application and the environment that its branch maps to:
quant_application: ${{ vars.QUANT_APPLICATION || github.event.repository.name }}. Do not hard-code another application name as the default.- No fixed environment name. Without an override, the init action maps
maintoproduction,developtodevelop, and other branches to an environment named after the branch. - Only the steps the deploy needs: checkout, QEMU and Buildx, init, build and push, compose, environment, and state. Settings such as scaling or idle sleep belong on the environment, not in each deploy.
- The Quant Cloud actions at
@v4, includingquantcdn/quant-cloud-compose-action@v4(it has the same inputs and output as v1).
Build platform
Section titled “Build platform”quant.architecture in the compose file’s x-quant-labels sets the CPU type of the task. The workflow’s platforms: setting sets the CPU type of the image. They must match, or the container stops at start with exec format error.
quant.architecture |
Build platforms: |
Runner |
|---|---|---|
ARM64 (the app templates) |
linux/arm64 |
ubuntu-24.04-arm (native), or ubuntu-latest with docker/setup-qemu-action (slower) |
X86_64 |
linux/amd64 |
ubuntu-latest |
The template workflows read the BUILD_PLATFORM and RUNNER_TYPE repository variables. Check the BUILD_PLATFORM default in your copy: for ARM64 it must be linux/arm64, or set the variable. If you change the architecture, change both.
An ARM64 build on an x86 runner uses emulation and is slower. Use an ARM runner (RUNNER_TYPE), or build architecture-independent output (static assets, JavaScript bundles) in a FROM --platform=$BUILDPLATFORM builder stage and install native modules in the target-platform stage.
quant/meta.json
Section titled “quant/meta.json”A template declares what it needs from Quant in quant/meta.json. The file is a JSON object, or an array that holds one object.
| Key | Kinds | Effect |
|---|---|---|
template_type |
all | "app" (Quant Cloud), "ssg" (static), or "base" (a base image) |
requires_db |
app | true: the wizard provisions a managed database |
requires_cache |
app | true: the wizard pre-selects a managed cache |
requires_s3 |
app | true: the wizard pre-selects object storage |
secrets |
app | [{"name": "X", "generate": "random", "length": 64}]: a random value of length characters, set as a secret on the production environment |
kv_stores |
static | KV stores to create, seed and link to the project |
project_settings |
static | Only {"enable_inline_fn": true}. Setup only turns a setting on |
title, summary, content, image, categories, tags, url |
all | Describe the template. No effect on what is created |
Who applies it:
| Reader | Keys |
|---|---|
The dashboard template wizard (templates in quantcdn-templates) |
requires_db, requires_cache, requires_s3, secrets (apps); kv_stores, project_settings (static) |
| Studio publish (the Studio site’s own repository) | kv_stores, project_settings |
| The GitHub deploy workflow | None. deploy-action deploys quant/edge-functions.json and quant/edge-rules.json |
A generated secret is set once, when the application is created. A new environment does not get production’s secrets; set them on each environment.
kv_stores
Section titled “kv_stores”{ "template_type": "ssg", "kv_stores": [ { "name": "orbit", "initial_values": [ { "key": "workspace:studio:settings", "value": { "name": "My workspace" } }, { "key": "signing-key", "generate": { "bytes": 32 }, "encrypted": true }, { "key": "auth:{sha256}", "generate": { "bytes": 32, "reveal": "once", "label": "Owner access key" }, "value": { "name": "{user_name}", "role": "owner" } } ] } ]}nameis lowercase, starts with a letter, and has at most 48 characters. The store ID is<organisation>-<project>-<name>.- Limits: 10 stores, 100 initial values in total, 16 KiB per value, 64 KiB in total. An invalid declaration fails setup before any store is created.
- Setup creates each store, writes the initial values, and links the store to the project. A key that already exists is never replaced.
- A plain value is stored as given; add
"encrypted": trueto encrypt it. - A generated secret (
generate.bytes, 16-64) is stored as lowercase hex. It is never shown and never rotated. - A one-time credential (
"reveal": "once") is shown once on the setup screen. Only its SHA-256 hash is stored, in place of{sha256}in the key.{sha256}appears exactly once, only in such a key. A one-time credential cannot be encrypted, and a store can have at most four. If it is lost, follow the template README’s reset steps. {user_name}in a value becomes the name of the person who creates the site (on Studio publish, the person who publishes).
Studio publish creates and links declared stores that the project does not link, and writes each declared key at most once, so a key that someone deleted stays deleted. It never creates one-time credentials.
Write your own template
Section titled “Write your own template”The dashboard template picker lists only repositories in the quantcdn-templates organisation. Your own template repository is not listed, and the wizard does not apply its meta.json. To reuse a template in your organisation, make it a GitHub template repository, create each site with Use this template, and follow Copy a template by hand. Keep a meta.json anyway: it records what each site needs, and Studio publish reads its kv_stores and project_settings.
An app template has this layout:
Dockerfile # FROM ghcr.io/quantcdn-templates/app-node or app-apache-phpdocker-compose.yml # what Quant Cloud importsdocker-compose.override.yml.example # local-only values; copy to docker-compose.override.yml.dockerignore.gitignore # include docker-compose.override.ymlREADME.mdquant/meta.jsonquant/entrypoints/ # start-up scripts, copied to /quant-entrypoint.d/.github/workflows/build-deploy.yaml- Follow the Docker Compose rules: size the task in
x-quant-labels, label the local databasequant.type: mysqlorpostgres, keepDB_*and other injected names out of the deployedenvironment:, and tag the image with the compose service name as its prefix. - Node apps on
app-nodelisten on port 3001 and expose 3000; PHP apps onapp-apache-phplisten on port 80 (base images). - Match the build platform to
quant.architecture.
A static template has package.json and the framework source, quant/meta.json ("template_type": "ssg"), and .github/workflows/deploy.yml with deploy-action and purge-action. Set dir: to the framework’s output directory, and guard the deploy steps on the credentials so the template repository itself, which has none, still verifies its build. A static + edge template adds quant/edge-functions.json, quant/edge-functions/*.js and quant/edge-rules.json (see Edge functions); its README must explain how to replace a lost one-time credential.
