Contribute a template
Add or fix a blueprint, validate it, and get it into the gallery.
Purpose — Every blueprint lives in templates/blueprints/ of the Notploy repository. Adding one is a normal pull request: create the folder, validate it locally, preview it in the gallery and open the PR. Missing a blueprint? The gallery's Add Template button opens a GitHub issue, and each template's Edit Template link points at its folder.
Repository layout
| Path | Role |
|---|---|
templates/blueprints/ | One folder per blueprint — the content you contribute. |
templates/build-scripts/ | Validators and the catalogue generator. |
templates/app/ | The gallery web app (Vite + React) served as a static site. |
templates/Dockerfile, templates/nginx.conf | Container image that publishes the gallery. |
Both templates/app and templates/build-scripts are workspace packages of the monorepo.
Add a blueprint
Create the folder. templates/blueprints/<id>/ — the id is lowercase and hyphenated, and
meta.json's id must match it exactly.
Write the compose file. Follow the rules of Blueprint anatomy: no
container_name, no networks, ports as bare numbers. Add an opt-out marker only when the
protocol truly requires host-published ports.
Describe the configuration. Add template.toml with the variables, environment, domains and
mounts the service needs — see Template configuration.
Add the metadata. Ship meta.json and the logo it references. Add instructions.md when the
app needs first-run guidance.
Validate and preview, then open the pull request.
Validate locally
The validators live in templates/build-scripts and are run from that directory:
cd templates/build-scripts
pnpm install
# template.toml against the compose file
pnpm validate-template -- --dir ../blueprints/<id>
# Compose rules (container names, networks, port formats)
pnpm validate-docker-compose -- --file ../blueprints/<id>/docker-compose.yml
# every meta.json in the catalogue (validate only, write nothing)
node generate-meta.js --check
# every github / website / docs link
node check-links.jsAdd -v to either validator for details of the services and domains it found. What each check enforces:
| Check | Fails when |
|---|---|
validate-template | template.toml is missing or invalid, a domain points at an unknown service, a mount lacks filePath/content, or a helper argument is malformed. |
validate-docker-compose | A compose file uses container_name, declares networks, or maps host:container ports without an opt-out marker. |
generate-meta.js | A meta.json is missing a required field, id and folder name differ, tags is empty, or the logo file does not exist. |
check-links | A link returns a broken status (403 counts as reachable, 429 is skipped as rate-limited). |
generate-meta.js resolves every path from its own location, so it can be run from anywhere in the
repository. It aggregates the per-blueprint files into app/public/meta.json, the catalogue the
gallery serves, and both pnpm dev and pnpm build of the gallery app run it automatically.
Preview the gallery
pnpm --filter=@notploy/templates-app devThe dev server regenerates the catalogue, copies the blueprints into the bundle and serves the
gallery locally. Because a local Notploy checkout reads templates/blueprints directly, the same
blueprint can be deployed from the panel right away — set NOTPLOY_TEMPLATES_DIR if your blueprints
live outside the checkout.
Publish
- The gallery is built from the repository root with
templates/Dockerfile(the pnpm workspace lives there): a multi-stage build that runspnpm --filter=@notploy/templates-app build, then serves the output with nginx on port80. - Release tags of the form
vX.Y.Z-templatespublish thenotploy-templatesimage, which is how templates.notploy.com is updated.
Checklist before opening a pull request
- Folder name and
meta.jsonidmatch. - Both validators and
generate-meta.js --checkpass. - Links resolve (
check-links.js). - The blueprint deploys from a local panel.
-
instructions.mdexplains any first-run step that is not obvious. - No real credentials, tokens or personal data anywhere in the files.