Versioning & git
Keep templates in a repository you already review and deploy from. Connect it once per account; every push becomes an immutable version, and every message records the version and the commit it rendered from.
Repository layout
templates/
welcome.twig body (Twig) — or welcome.liquid
welcome.text.twig optional plain-text part
welcome.json optional sidecar: subject, name, variables,
is_sensitive, content_retention_days, layout
layouts/
base.twig optional; the body replaces {# body #}The file name is the slug. The extension picks the engine; a sidecar that disagrees is an error, not a guess. A retention number above your plan ceiling is lowered to it, never refused. Everything is compile-checked at sync, and one bad file holds back the whole push — a sync is a single transaction.
Connecting a repository
- Templates → Sync from git → paste the SSH clone URL, the branch, and an optional folder inside the repo.
- We generate an ed25519 deploy key. Add the public half to the repository as a read-only deploy key (GitHub: Settings → Deploy keys; GitLab: Settings → Repository → Deploy keys). The private half never leaves our keyring.
- Add the push webhook URL shown once at connect. The token in the URL is the secret; the body is ignored. Without it, changes still arrive on the hourly fetch.
- Press Sync now.
We only ever read. The remote must be a public host — nothing on a private network — and an HTTPS URL is accepted only for a public repository, never with a token in it.
What a sync does
A new version is minted only when the subject, a body, the engine or the variables changed; a metadata-only edit updates the template without a version. Versions are immutable and never deleted. A file removed from the repository leaves its template sendable and listed as an orphan — retiring it is a deliberate act from the CLI, never a side effect of a push. A template created in the panel is never overwritten by a file of the same slug; the sync stops and says so.