Skip to content

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.

When you fork or copy a template on GitHub instead of using the template wizard, nothing in quant/meta.json is applied for you.

  1. 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).
  2. Add the GitHub secrets and variables that the wizard would set (see What happens behind the scenes). Set QUANT_APPLICATION to your application name; without it, the app workflow uses the repository name.
  3. On QuantGov, set the QUANT_BASE_URL variable to https://dash.quantgov.cloud/api/v3 (apps), and give the deploy and purge steps endpoint: https://api.quantgov.cloud/v1 (static).
  4. Create what quant/meta.json declares: secrets on the environment, KV stores (create, link to the project, write the initial values), and project settings such as inline functions.
  5. For an app, check that the build platform matches the architecture (below).
  6. You can delete ci.yml. It maintains the template itself.
  7. Push to main. The init action deploys main to the production environment.

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 main to production, develop to develop, 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, including quantcdn/quant-cloud-compose-action@v4 (it has the same inputs and output as v1).

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.

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.

{
"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" }
}
]
}
]
}
  • name is 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": true to 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.

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-php
docker-compose.yml # what Quant Cloud imports
docker-compose.override.yml.example # local-only values; copy to docker-compose.override.yml
.dockerignore
.gitignore # include docker-compose.override.yml
README.md
quant/meta.json
quant/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 database quant.type: mysql or postgres, keep DB_* and other injected names out of the deployed environment:, and tag the image with the compose service name as its prefix.
  • Node apps on app-node listen on port 3001 and expose 3000; PHP apps on app-apache-php listen 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.