Introducing kik generate: schema driven plates on Kikplate
By Moeid Heidari · 8 min read · Jun 22, 2026
Kikplate started as a simple idea. A plate is a project template backed by a real GitHub repository, and the CLI lets you pull one down in seconds. That part hasn't changed. What has changed is how a plate describes itself and how the CLI turns that description into a working project on your machine.
The new feature is called generate. It is built around a typed schema inside the plate manifest, a CLI command that reads that schema and renders every templated file in the repository, and a renamed CLI binary. This article walks through all of it: the new manifest file, the schema tab on the plate page, the generate command and its flags, a full walkthrough using a real plate, and what the migration away from the old manifest looks like.
From kikplate.yaml to plate.yaml
Every plate used to be defined by a single file at the root of its repository called kikplate.yaml. That file carried only descriptive metadata: a name, description, category, owner, tags, and, once a submission was approved, a verification token. The CLI would clone the repository, strip that file out, and hand you the rest of the contents as your new project. There was no concept of variables, no conditional files, and nothing for the platform to render. Cloning was the whole mechanism.
The new manifest is called plate.yaml. It carries everything kikplate.yaml used to carry, plus a schema block that declares the variables a plate accepts, a modules block for toggling optional pieces of the template on or off, and a files block that maps every output path in the generated project to a template source. In short, kikplate.yaml described a plate. plate.yaml describes a generator.
You do not need to throw away an existing plate to adopt this. Kikplate still reads kikplate.yaml today so that owners can migrate at their own pace. That support is temporary, though, and it will be removed in a future release. If you maintain a plate, the practical move is to add a plate.yaml file now, even a minimal one, rather than waiting for the cutover.
Anatomy of a plate.yaml file
The clearest way to see the new format is to look at a real plate. The nginx http server starter plate publishes a minimal, production-ready NGINX static server, and its plate.yaml looks like this:
name: nginx-http-server-starter
owner: kikplate-public
verification_token: d4864f00-8988-42bf-aa1d-54ea18146f76
description: Minimal production-ready NGINX static HTTP server with modular config and clean structure.
version: 1.0.0
category: backend
tags:
- nginx
- http
- static
- starter
- boilerplate
- web-server
schema:
projectName:
type: string
default: nginx-http-starter
projectDescription:
type: string
default: Minimal static server starter with clean structure and production-ready NGINX config.
kikplateSlug:
type: string
default: nginx-http-starter
kikplateBadgeColor:
type: string
default: 0366d6
localPort:
type: int
default: 8080
containerPort:
type: int
default: 80
containerName:
type: string
default: anginx-http-starter
nginxImage:
type: string
default: nginx:stable-alpine
workerConnections:
type: int
default: 1024
keepaliveTimeout:
type: int
default: 65
gzipEnabled:
type: bool
default: true
gzipMinLength:
type: int
default: 1024
localRoot:
type: string
default: ./public
containerRoot:
type: string
default: /usr/share/nginx/html
prodCacheExpires:
type: string
default: 30d
prodCacheMaxAge:
type: int
default: 2592000
modules:
docker:
enabled: true
cacheHeaders:
enabled: true
files:
- path: .dockerignore
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.dockerignore.tmpl
condition: modules.docker.enabled
- path: .editorconfig
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.editorconfig.tmpl
- path: .gitignore
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.gitignore.tmpl
- path: LICENSE
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/LICENSE.tmpl
- path: README.md
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/README.md.tmpl
- path: conf.d/active.conf
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/active.conf.tmpl
- path: conf.d/dev.conf
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/dev.conf.tmpl
- path: conf.d/prod.conf
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/prod.conf.tmpl
- path: docker-compose.yaml
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/docker-compose.yaml.tmpl
condition: modules.docker.enabled
- path: dockerFile
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/dockerFile.tmpl
condition: modules.docker.enabled
- path: mime.types
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/mime.types.tmpl
- path: nginx.conf
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/nginx.conf.tmpl
- path: public/index.html
template: https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/public/index.html.tmpl
A few things are worth calling out.
- Everything above
schemais the same metadata you already know fromkikplate.yaml: name, owner, description, category, tags, and the verification token issued during submission. - The
schemablock is new. Each key is a variable the plate exposes, with atype(string,int, orboolseen here) and adefaultvalue. These are the values a consumer of the plate can override at generation time. - The
modulesblock groups related toggles together. Here, thedockermodule controls whether Docker-related files get generated at all, and is referenced from thefilesblock as a condition. - The
filesblock is the actual generator definition. Each entry maps an output path in the new project to a template file in the plate's owntemplatesdirectory, written with the.tmplextension so the engine knows it needs rendering rather than a plain copy. Some entries carry acondition, which is evaluated against themodulesblock, so an output file is only produced when its module is enabled.
This is what makes generate fundamentally different from the old clone-and-strip approach. The CLI is no longer just copying files. It is reading a schema, applying your values and module choices on top of the defaults, and rendering each template into the matching output path.
The schema tab on the plate page
On kikplate.dev, a plate page now has a tab dedicated to its schema. It lists every variable declared in plate.yaml along with its type and default value, so you can see exactly what a plate expects before you ever touch a terminal.
The CLI is now kik
The CLI binary itself has been renamed. What used to be invoked as kikplate is now invoked as kik. Every subcommand you already know — search, describe, submit, verify, and the rest — still exists under the new root command. The headline addition is the generate subcommand, which is what actually exercises the new schema.
Installing the CLI
The install paths follow the same mechanisms Kikplate has always used: a Homebrew tap on macOS and Linux, a Scoop bucket on Windows, release archives for any platform, or building from source with Go. Only the binary name has changed, from kikplate to kik.
macOS and Linux, via Homebrew
brew tap kikplate/kikplate
brew install kik
Windows, via Scoop
scoop bucket add kikplate https://github.com/kikplate/scoop-bucket.git
scoop install kik
Manual install from a release archive, any platform
Download the archive that matches your platform from the project's GitHub Releases page, then install the binary onto your PATH.
# Linux or macOS
tar -xzf kik-<version>-linux-amd64.tar.gz
sudo install kik-<version>-linux-amd64 /usr/local/bin/kik
# Windows, PowerShell
Expand-Archive .\kik-<version>-windows-amd64.zip -DestinationPath .
Move-Item .\kik-<version>-windows-amd64.exe kik.exe
# add the folder containing kik.exe to PATH
Build from source
git clone https://github.com/kikplate/kikplate.git
cd kikplate/cli
go build -o kik .
sudo mv kik /usr/local/bin/kik
Once installed, confirm it works:
kik --help
Walking through kik generate
The generate command supports two modes. You can point it at a plate.yaml sitting on disk, which is the natural workflow for a plate author iterating on their own template, or you can point it at a published plate by its slug, which is the natural workflow for someone consuming a plate from the registry. Both modes accept a values file that overrides whatever defaults the schema declares.
Step 1: pick or inspect a plate
Browse kikplate.dev and open a plate page to read its schema tab, or use the CLI to search and read the manifest directly from the repository. We will use nginx-http-server-starter as our example throughout.
Step 2: write a values file
Create a values.yaml file with only the keys you want to override. Anything you leave out falls back to the default declared in the plate's schema.
projectName: my-static-site
projectDescription: A small static site served by NGINX, generated from a Kikplate plate
localPort: 9090
nginxImage: nginx:stable-alpine
gzipEnabled: true
prodCacheExpires: 7d
Step 3: generate from a local checkout of the template
If you have cloned the plate's repository, or you are the author working inside it, point generate at the directory and tell it where to write the result:
kik generate --template . -f values.yaml --output-dir ./generated-project
The --template flag takes a path to a directory containing a plate.yaml. The -f flag takes the values file from step 2. The --output-dir flag is where the rendered project lands.
Step 4: generate from the published plate by slug
If you simply want to consume the plate without cloning anything yourself, drop the --template flag and pass the plate's slug instead:
kik generate nginx-http-starter -f values.yaml
This pulls the same plate.yaml and template set from the registry's source of truth — your repository — and renders it the same way the local mode does.
Both invocations evaluate the modules block, so if you wanted to skip Docker support entirely you would set modules.docker.enabled to false in your values file, and every conditioned file in the files block tied to that module simply would not be written.
For the exhaustive list of flags, including anything added after this article was written, run:
kik generate --help
Step 5: run the generated project
For this particular plate, the generated output is a ready-to-serve NGINX project. Enter the directory and start the server with the included config:
cd generated-project
nginx -c $(pwd)/nginx.conf -p $(pwd)
Open http://localhost:9090, or whichever port you set in localPort, in your browser.
Migrating an existing plate
If you maintain a plate that still only has a kikplate.yaml, here is the practical path.
- Keep
kikplate.yamlin place for now. Kikplate still reads it, so nothing breaks today. - Add a
plate.yamlalongside it. Carry over name, owner, description, category, tags, and the verification token unchanged. - Decide which parts of your repository should be parameterized, and move them into a
templatesdirectory with a.tmplextension on each file. - Build out the
schemablock for every variable those templates reference, giving each one a sensible default sogenerateworks out of the box with no values file at all. - If any part of the repository is optional, group it behind a key in the
modulesblock and add aconditionon the matchingfilesentries. - Once
plate.yamlis in place and tested withkik generate --template ., removekikplate.yaml. Support for it will go away in an upcoming release, so there is no advantage to leaving it around onceplate.yamlis verified to work.
The two files can coexist during this transition, which is the whole point of the gradual rollout. There is no hard cutover date forcing every plate to migrate overnight, but there is also no reason to wait until the deprecation lands to start.
Closing thoughts
The shift from kikplate.yaml to plate.yaml, and from a clone-based scaffold to a schema-driven generate, changes what a plate actually is. It used to be a repository you copied. Now it is a small, typed program: declare your variables, declare your optional modules, declare which files depend on which, and let kik generate do the rendering. If you publish plates, this is worth adopting early. If you consume them, kik generate -f values.yaml is now the fastest path from a plate you found on kikplate.dev to a project running on your machine.
Top comments (0)