<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Moeid Heidari</title>
    <description>The latest articles on DEV Community by Moeid Heidari (@moeidheidari).</description>
    <link>https://dev.to/moeidheidari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3755482%2F438dc723-5717-4075-8d2e-4dc16e3f00e9.png</url>
      <title>DEV Community: Moeid Heidari</title>
      <link>https://dev.to/moeidheidari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moeidheidari"/>
    <language>en</language>
    <item>
      <title>What If Your Project Starter Knew Exactly What You Needed</title>
      <dc:creator>Moeid Heidari</dc:creator>
      <pubDate>Tue, 07 Jul 2026 19:59:25 +0000</pubDate>
      <link>https://dev.to/moeidheidari/what-if-your-project-starter-knew-exactly-what-you-needed-3gf8</link>
      <guid>https://dev.to/moeidheidari/what-if-your-project-starter-knew-exactly-what-you-needed-3gf8</guid>
      <description>&lt;h2&gt;
  
  
  Introducing kik generate: schema driven plates on Kikplate
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;By Moeid Heidari · 8 min read · Jun 22, 2026&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The new feature is called &lt;code&gt;generate&lt;/code&gt;. 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 &lt;code&gt;generate&lt;/code&gt; command and its flags, a full walkthrough using a real plate, and what the migration away from the old manifest looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  From kikplate.yaml to plate.yaml
&lt;/h2&gt;

&lt;p&gt;Every plate used to be defined by a single file at the root of its repository called &lt;code&gt;kikplate.yaml&lt;/code&gt;. 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.&lt;/p&gt;

&lt;p&gt;The new manifest is called &lt;code&gt;plate.yaml&lt;/code&gt;. It carries everything &lt;code&gt;kikplate.yaml&lt;/code&gt; used to carry, plus a &lt;code&gt;schema&lt;/code&gt; block that declares the variables a plate accepts, a &lt;code&gt;modules&lt;/code&gt; block for toggling optional pieces of the template on or off, and a &lt;code&gt;files&lt;/code&gt; block that maps every output path in the generated project to a template source. In short, &lt;code&gt;kikplate.yaml&lt;/code&gt; described a plate. &lt;code&gt;plate.yaml&lt;/code&gt; describes a generator.&lt;/p&gt;

&lt;p&gt;You do not need to throw away an existing plate to adopt this. Kikplate still reads &lt;code&gt;kikplate.yaml&lt;/code&gt; 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 &lt;code&gt;plate.yaml&lt;/code&gt; file now, even a minimal one, rather than waiting for the cutover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a plate.yaml file
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;plate.yaml&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-http-server-starter&lt;/span&gt;
&lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kikplate-public&lt;/span&gt;
&lt;span class="na"&gt;verification_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;d4864f00-8988-42bf-aa1d-54ea18146f76&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Minimal production-ready NGINX static HTTP server with modular config and clean structure.&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;

&lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;static&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;starter&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;boilerplate&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web-server&lt;/span&gt;

&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-http-starter&lt;/span&gt;
  &lt;span class="na"&gt;projectDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Minimal static server starter with clean structure and production-ready NGINX config.&lt;/span&gt;
  &lt;span class="na"&gt;kikplateSlug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-http-starter&lt;/span&gt;
  &lt;span class="na"&gt;kikplateBadgeColor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0366d6&lt;/span&gt;
  &lt;span class="na"&gt;localPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="na"&gt;containerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anginx-http-starter&lt;/span&gt;
  &lt;span class="na"&gt;nginxImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:stable-alpine&lt;/span&gt;
  &lt;span class="na"&gt;workerConnections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;
  &lt;span class="na"&gt;keepaliveTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65&lt;/span&gt;
  &lt;span class="na"&gt;gzipEnabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bool&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;gzipMinLength&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;
  &lt;span class="na"&gt;localRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./public&lt;/span&gt;
  &lt;span class="na"&gt;containerRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/share/nginx/html&lt;/span&gt;
  &lt;span class="na"&gt;prodCacheExpires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30d&lt;/span&gt;
  &lt;span class="na"&gt;prodCacheMaxAge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2592000&lt;/span&gt;

&lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;cacheHeaders&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.dockerignore&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.dockerignore.tmpl&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;modules.docker.enabled&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.editorconfig&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.editorconfig.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.gitignore&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/.gitignore.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LICENSE&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/LICENSE.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;README.md&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/README.md.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conf.d/active.conf&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/active.conf.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conf.d/dev.conf&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/dev.conf.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conf.d/prod.conf&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/conf.d/prod.conf.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.yaml&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/docker-compose.yaml.tmpl&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;modules.docker.enabled&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dockerFile&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/dockerFile.tmpl&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;modules.docker.enabled&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mime.types&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/mime.types.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx.conf&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/nginx.conf.tmpl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public/index.html&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/kikplate/nginx-http-server-starter/main/templates/public/index.html.tmpl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things are worth calling out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything above &lt;code&gt;schema&lt;/code&gt; is the same metadata you already know from &lt;code&gt;kikplate.yaml&lt;/code&gt;: name, owner, description, category, tags, and the verification token issued during submission.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;schema&lt;/code&gt; block is new. Each key is a variable the plate exposes, with a &lt;code&gt;type&lt;/code&gt; (&lt;code&gt;string&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, or &lt;code&gt;bool&lt;/code&gt; seen here) and a &lt;code&gt;default&lt;/code&gt; value. These are the values a consumer of the plate can override at generation time.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;modules&lt;/code&gt; block groups related toggles together. Here, the &lt;code&gt;docker&lt;/code&gt; module controls whether Docker-related files get generated at all, and is referenced from the &lt;code&gt;files&lt;/code&gt; block as a condition.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;files&lt;/code&gt; block is the actual generator definition. Each entry maps an output path in the new project to a template file in the plate's own &lt;code&gt;templates&lt;/code&gt; directory, written with the &lt;code&gt;.tmpl&lt;/code&gt; extension so the engine knows it needs rendering rather than a plain copy. Some entries carry a &lt;code&gt;condition&lt;/code&gt;, which is evaluated against the &lt;code&gt;modules&lt;/code&gt; block, so an output file is only produced when its module is enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what makes &lt;code&gt;generate&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The schema tab on the plate page
&lt;/h2&gt;

&lt;p&gt;On kikplate.dev, a plate page now has a tab dedicated to its schema. It lists every variable declared in &lt;code&gt;plate.yaml&lt;/code&gt; along with its type and default value, so you can see exactly what a plate expects before you ever touch a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CLI is now &lt;code&gt;kik&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The CLI binary itself has been renamed. What used to be invoked as &lt;code&gt;kikplate&lt;/code&gt; is now invoked as &lt;code&gt;kik&lt;/code&gt;. Every subcommand you already know — &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;submit&lt;/code&gt;, &lt;code&gt;verify&lt;/code&gt;, and the rest — still exists under the new root command. The headline addition is the &lt;code&gt;generate&lt;/code&gt; subcommand, which is what actually exercises the new schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the CLI
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;kikplate&lt;/code&gt; to &lt;code&gt;kik&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS and Linux, via Homebrew&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap kikplate/kikplate
brew &lt;span class="nb"&gt;install &lt;/span&gt;kik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows, via Scoop&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scoop bucket add kikplate https://github.com/kikplate/scoop-bucket.git
scoop &lt;span class="nb"&gt;install &lt;/span&gt;kik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Manual install from a release archive, any platform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download the archive that matches your platform from the project's GitHub Releases page, then install the binary onto your PATH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Linux or macOS&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; kik-&amp;lt;version&amp;gt;-linux-amd64.tar.gz
&lt;span class="nb"&gt;sudo install &lt;/span&gt;kik-&amp;lt;version&amp;gt;-linux-amd64 /usr/local/bin/kik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Windows, PowerShell&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Expand-Archive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\kik-&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;-windows-amd64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-DestinationPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Move-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\kik-&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;-windows-amd64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;kik.exe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# add the folder containing kik.exe to PATH&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build from source&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kikplate/kikplate.git
&lt;span class="nb"&gt;cd &lt;/span&gt;kikplate/cli
go build &lt;span class="nt"&gt;-o&lt;/span&gt; kik &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;kik /usr/local/bin/kik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, confirm it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kik &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Walking through kik generate
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;generate&lt;/code&gt; command supports two modes. You can point it at a &lt;code&gt;plate.yaml&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: pick or inspect a plate
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;nginx-http-server-starter&lt;/code&gt; as our example throughout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: write a values file
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;values.yaml&lt;/code&gt; file with only the keys you want to override. Anything you leave out falls back to the default declared in the plate's schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-static-site&lt;/span&gt;
&lt;span class="na"&gt;projectDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A small static site served by NGINX, generated from a Kikplate plate&lt;/span&gt;
&lt;span class="na"&gt;localPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9090&lt;/span&gt;
&lt;span class="na"&gt;nginxImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:stable-alpine&lt;/span&gt;
&lt;span class="na"&gt;gzipEnabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;prodCacheExpires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;7d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: generate from a local checkout of the template
&lt;/h3&gt;

&lt;p&gt;If you have cloned the plate's repository, or you are the author working inside it, point &lt;code&gt;generate&lt;/code&gt; at the directory and tell it where to write the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kik generate &lt;span class="nt"&gt;--template&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml &lt;span class="nt"&gt;--output-dir&lt;/span&gt; ./generated-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--template&lt;/code&gt; flag takes a path to a directory containing a &lt;code&gt;plate.yaml&lt;/code&gt;. The &lt;code&gt;-f&lt;/code&gt; flag takes the values file from step 2. The &lt;code&gt;--output-dir&lt;/code&gt; flag is where the rendered project lands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: generate from the published plate by slug
&lt;/h3&gt;

&lt;p&gt;If you simply want to consume the plate without cloning anything yourself, drop the &lt;code&gt;--template&lt;/code&gt; flag and pass the plate's slug instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kik generate nginx-http-starter &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pulls the same &lt;code&gt;plate.yaml&lt;/code&gt; and template set from the registry's source of truth — your repository — and renders it the same way the local mode does.&lt;/p&gt;

&lt;p&gt;Both invocations evaluate the &lt;code&gt;modules&lt;/code&gt; block, so if you wanted to skip Docker support entirely you would set &lt;code&gt;modules.docker.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in your values file, and every conditioned file in the &lt;code&gt;files&lt;/code&gt; block tied to that module simply would not be written.&lt;/p&gt;

&lt;p&gt;For the exhaustive list of flags, including anything added after this article was written, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kik generate &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: run the generated project
&lt;/h3&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;generated-project
nginx &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/nginx.conf &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:9090&lt;/code&gt;, or whichever port you set in &lt;code&gt;localPort&lt;/code&gt;, in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating an existing plate
&lt;/h2&gt;

&lt;p&gt;If you maintain a plate that still only has a &lt;code&gt;kikplate.yaml&lt;/code&gt;, here is the practical path.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep &lt;code&gt;kikplate.yaml&lt;/code&gt; in place for now. Kikplate still reads it, so nothing breaks today.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;plate.yaml&lt;/code&gt; alongside it. Carry over name, owner, description, category, tags, and the verification token unchanged.&lt;/li&gt;
&lt;li&gt;Decide which parts of your repository should be parameterized, and move them into a &lt;code&gt;templates&lt;/code&gt; directory with a &lt;code&gt;.tmpl&lt;/code&gt; extension on each file.&lt;/li&gt;
&lt;li&gt;Build out the &lt;code&gt;schema&lt;/code&gt; block for every variable those templates reference, giving each one a sensible default so &lt;code&gt;generate&lt;/code&gt; works out of the box with no values file at all.&lt;/li&gt;
&lt;li&gt;If any part of the repository is optional, group it behind a key in the &lt;code&gt;modules&lt;/code&gt; block and add a &lt;code&gt;condition&lt;/code&gt; on the matching &lt;code&gt;files&lt;/code&gt; entries.&lt;/li&gt;
&lt;li&gt;Once &lt;code&gt;plate.yaml&lt;/code&gt; is in place and tested with &lt;code&gt;kik generate --template .&lt;/code&gt;, remove &lt;code&gt;kikplate.yaml&lt;/code&gt;. Support for it will go away in an upcoming release, so there is no advantage to leaving it around once &lt;code&gt;plate.yaml&lt;/code&gt; is verified to work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;The shift from &lt;code&gt;kikplate.yaml&lt;/code&gt; to &lt;code&gt;plate.yaml&lt;/code&gt;, and from a clone-based scaffold to a schema-driven &lt;code&gt;generate&lt;/code&gt;, 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 &lt;code&gt;kik generate&lt;/code&gt; do the rendering. If you publish plates, this is worth adopting early. If you consume them, &lt;code&gt;kik generate -f values.yaml&lt;/code&gt; is now the fastest path from a plate you found on kikplate.dev to a project running on your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://kikplate.dev" rel="noopener noreferrer"&gt;kikplate.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>boilerplate</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Crossview: Finally Seeing What’s Really Happening in Your Crossplane Control Plane</title>
      <dc:creator>Moeid Heidari</dc:creator>
      <pubDate>Thu, 05 Feb 2026 20:26:35 +0000</pubDate>
      <link>https://dev.to/moeidheidari/crossview-finally-seeing-whats-really-happening-in-your-crossplane-control-plane-44ne</link>
      <guid>https://dev.to/moeidheidari/crossview-finally-seeing-whats-really-happening-in-your-crossplane-control-plane-44ne</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wifvw6wnkkqwqr6mtfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wifvw6wnkkqwqr6mtfw.png" alt="Crossview dashboard showing composite resources and their status" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever worked with &lt;strong&gt;Crossplane&lt;/strong&gt;, you probably recognize this situation:&lt;/p&gt;

&lt;p&gt;You apply a claim.&lt;br&gt;&lt;br&gt;
Resources get created somewhere.&lt;br&gt;&lt;br&gt;
And then you’re left stitching together YAML, &lt;code&gt;kubectl&lt;/code&gt; output, and mental models to understand what’s actually going on.&lt;/p&gt;

&lt;p&gt;That gap is exactly why &lt;strong&gt;Crossview&lt;/strong&gt; exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Crossview?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Crossview&lt;/strong&gt; is an open‑source &lt;strong&gt;UI dashboard for Crossplane&lt;/strong&gt; that helps you visualize, explore, and understand your Crossplane‑managed infrastructure. It provides focused tooling for Crossplane workflows instead of generic Kubernetes resources, letting you see the things that matter without piecing them together manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;Crossview already delivers significant capabilities out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real‑Time Resource Watching — Monitor any Kubernetes resource with live updates via Kubernetes informers and WebSockets.&lt;/li&gt;
&lt;li&gt;Multi‑Cluster Support — Manage and switch between multiple Kubernetes contexts seamlessly from a single interface.&lt;/li&gt;
&lt;li&gt;Resource Visualization — Browse and visualize Crossplane resources, including providers, XRDs, compositions, claims, and more.&lt;/li&gt;
&lt;li&gt;Resource Details — View comprehensive information like status conditions, metadata, events, and relationships for each resource.&lt;/li&gt;
&lt;li&gt;Authentication &amp;amp; Authorization — Support for OIDC and SAML authentication, integrating with identity providers such as Auth0, Okta, Azure AD, and others.&lt;/li&gt;
&lt;li&gt;High‑Performance Backend — Built with Go using the Gin framework for optimal performance and efficient API interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crossview already gives you a &lt;em&gt;true visual control plane&lt;/em&gt; experience tailored for Crossplane — so you don’t have to translate mental models into YAML every time you want to answer a question about infrastructure state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Built It
&lt;/h2&gt;

&lt;p&gt;Crossplane is powerful, but its abstraction can make day‑to‑day operations harder than they should be.&lt;/p&gt;

&lt;p&gt;Simple questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why is this composite not ready?&lt;/li&gt;
&lt;li&gt;Which managed resource failed?&lt;/li&gt;
&lt;li&gt;What does this claim actually create?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;often require jumping between multiple commands and outputs.&lt;/p&gt;

&lt;p&gt;Crossview reduces that cognitive load and makes the control plane easier to operate and reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Is It For?
&lt;/h2&gt;

&lt;p&gt;Crossview is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Platform engineers running Crossplane in production&lt;/li&gt;
&lt;li&gt;Teams onboarding users to platforms built on Crossplane&lt;/li&gt;
&lt;li&gt;Anyone who wants better visibility into Crossplane‑managed infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever felt blind while debugging Crossplane, Crossview is built for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source and Community‑Driven
&lt;/h2&gt;

&lt;p&gt;Crossview is fully open source, and community feedback plays a big role in shaping the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/corpobit/crossview" rel="noopener noreferrer"&gt;https://github.com/corpobit/crossview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs and Helm charts are available via the repo and Artifact Hub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback, issues, and contributions are all welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The goal of Crossview is simple: make Crossplane infrastructure &lt;strong&gt;visible, understandable, and easier to operate&lt;/strong&gt;. It already ships with real‑time watching, multi‑cluster support, rich resource details, and modern authentication integrations — giving you a dashboard that truly complements CLI workflows.&lt;/p&gt;

&lt;p&gt;If you’re using Crossplane, I’d love to hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What’s the hardest part to debug today?&lt;/li&gt;
&lt;li&gt;What visibility do you wish you had?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s improve the Crossplane experience together.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>react</category>
      <category>cloud</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
