<?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>Production-Ready Docker Compose Collection with kikplate</title>
      <dc:creator>Moeid Heidari</dc:creator>
      <pubDate>Fri, 17 Jul 2026 10:26:54 +0000</pubDate>
      <link>https://dev.to/moeidheidari/production-ready-docker-compose-collection-with-kikplate-1imn</link>
      <guid>https://dev.to/moeidheidari/production-ready-docker-compose-collection-with-kikplate-1imn</guid>
      <description>&lt;h2&gt;
  
  
  Docker Compose Plates: Reusable Infrastructure Stacks with kikplate
&lt;/h2&gt;

&lt;p&gt;Infrastructure setup is one of the most repeated tasks in software development. Every new project needs a database, a cache, a message broker, or an observability stack. Teams copy configurations from old projects, adjust port numbers, forget to add health checks, use unofficial images, and eventually end up with inconsistent setups across their environments.&lt;/p&gt;

&lt;p&gt;This article walks through a curated collection of twenty Docker Compose plates built for the &lt;strong&gt;kikplate&lt;/strong&gt; template generation system. Each plate is a parameterised, versioned, composable unit that generates a production-ready stack from a single command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kikplate/docker-compose-plates" rel="noopener noreferrer"&gt;Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kikplate.dev" rel="noopener noreferrer"&gt;Kikplate.dev&lt;/a&gt;&lt;/p&gt;


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

&lt;p&gt;kikplate is a developer toolchain for generating project files from versioned, schema-driven templates.&lt;/p&gt;

&lt;p&gt;A plate lives on its own Git branch. It defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A typed schema of input variables&lt;/li&gt;
&lt;li&gt;Optional feature modules&lt;/li&gt;
&lt;li&gt;A set of template files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Templates are fetched from GitHub, rendered with the provided values, and written to a local output directory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install on macOS and Linux
&lt;/h2&gt;


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

&lt;/div&gt;

&lt;h2&gt;
  
  
  Install on Windows
&lt;/h2&gt;


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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Plate Format
&lt;/h2&gt;

&lt;p&gt;Every plate in the collection follows the same directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plate.yaml          schema, modules, and file definitions
values.yaml         default values for all schema variables
templates/
    docker-compose.yml.tmpl     main compose template
    .env.tmpl                   secrets template
    README.md.tmpl              usage documentation
    ...                         additional config files where needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;plate.yaml&lt;/code&gt; file acts as the manifest.&lt;/p&gt;

&lt;p&gt;Example: the PostgreSQL plate.&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;postgres&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;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PostgreSQL 16 database with optional pgAdmin 4 web interface,&lt;/span&gt;
  &lt;span class="s"&gt;persistent named volumes, health checks, and bridge network isolation.&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;database&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;postgres&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pgadmin&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-compose&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;postgres&lt;/span&gt;

  &lt;span class="na"&gt;postgresVersion&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16"&lt;/span&gt;

  &lt;span class="na"&gt;postgresUser&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;app&lt;/span&gt;

  &lt;span class="na"&gt;postgresDb&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;app&lt;/span&gt;

  &lt;span class="na"&gt;postgresPort&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;5432&lt;/span&gt;

  &lt;span class="na"&gt;timezone&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;UTC&lt;/span&gt;

  &lt;span class="na"&gt;sharedBuffers&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128MB"&lt;/span&gt;

  &lt;span class="na"&gt;maxConnections&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;100&lt;/span&gt;

  &lt;span class="na"&gt;pgadminVersion&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8"&lt;/span&gt;

  &lt;span class="na"&gt;pgadminEmail&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;admin@example.com&lt;/span&gt;

  &lt;span class="na"&gt;pgadminPort&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;5050&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;pgadmin&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;docker-compose.yml&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/docker-compose-plates/postgres/templates/docker-compose.yml.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;.env&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/docker-compose-plates/postgres/templates/.env.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/docker-compose-plates/postgres/templates/README.md.tmpl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Schema
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;schema&lt;/code&gt; section defines every configurable value, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type&lt;/li&gt;
&lt;li&gt;Default value&lt;/li&gt;
&lt;li&gt;Validation rules (when applicable)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Modules
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;modules&lt;/code&gt; section defines optional capabilities that can be enabled or disabled during generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Files
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;files&lt;/code&gt; section specifies every generated output file and the remote template that should be rendered.&lt;/p&gt;




&lt;h2&gt;
  
  
  values.yaml
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;values.yaml&lt;/code&gt; file is a flat copy of all schema defaults and serves as the primary customization point.&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
&lt;span class="na"&gt;postgresVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16"&lt;/span&gt;
&lt;span class="na"&gt;postgresUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
&lt;span class="na"&gt;postgresDb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
&lt;span class="na"&gt;postgresPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
&lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UTC"&lt;/span&gt;
&lt;span class="na"&gt;sharedBuffers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128MB"&lt;/span&gt;
&lt;span class="na"&gt;maxConnections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
&lt;span class="na"&gt;pgadminVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8"&lt;/span&gt;
&lt;span class="na"&gt;pgadminEmail&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin@example.com"&lt;/span&gt;
&lt;span class="na"&gt;pgadminPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5050&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;pgadmin&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Gets Generated
&lt;/h2&gt;

&lt;p&gt;Running:&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 kikplate-public/postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;produces three files.&lt;/p&gt;




&lt;h2&gt;
  
  
  docker-compose.yml
&lt;/h2&gt;

&lt;p&gt;The Compose file is rendered from the template. Image versions, container names, ports, command flags, network names, and optional services are generated from the provided schema values.&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16-alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp-postgres&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;stop_grace_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
    &lt;span class="na"&gt;security_opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;no-new-privileges:true&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_DB}&lt;/span&gt;
      &lt;span class="na"&gt;PGTZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UTC&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="s"&gt;postgres&lt;/span&gt;
        &lt;span class="s"&gt;-c shared_buffers=128MB&lt;/span&gt;
        &lt;span class="s"&gt;-c max_connections=100&lt;/span&gt;
        &lt;span class="s"&gt;-c timezone=UTC&lt;/span&gt;
        &lt;span class="s"&gt;-c log_timezone=UTC&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMD-SHELL"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pg_isready&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-U&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-d&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${POSTGRES_DB}"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
      &lt;span class="na"&gt;start_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
    &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json-file&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;max-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10m"&lt;/span&gt;
        &lt;span class="na"&gt;max-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db_net&lt;/span&gt;

  &lt;span class="na"&gt;pgadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dpage/pgadmin4:8&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp-pgadmin&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;stop_grace_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
    &lt;span class="na"&gt;security_opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;no-new-privileges:true&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_EMAIL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${PGADMIN_EMAIL}&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${PGADMIN_PASSWORD}&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;True"&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_LISTEN_PORT&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;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5050:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pgadmin_data:/var/lib/pgadmin&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&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;service_healthy&lt;/span&gt;
    &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json-file&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;max-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10m"&lt;/span&gt;
        &lt;span class="na"&gt;max-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db_net&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pgadmin_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db_net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  .env
&lt;/h2&gt;

&lt;p&gt;Secrets and sensitive values are generated into a separate environment file.&lt;/p&gt;

&lt;p&gt;Placeholder values make it obvious what should be changed before a deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_USER=app
POSTGRES_PASSWORD=changeme
POSTGRES_DB=app

PGADMIN_EMAIL=admin@example.com
PGADMIN_PASSWORD=changeme
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  README.md
&lt;/h2&gt;

&lt;p&gt;A project-specific README is generated alongside the stack.&lt;/p&gt;

&lt;p&gt;The rendered documentation includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Startup instructions&lt;/li&gt;
&lt;li&gt;Service URLs&lt;/li&gt;
&lt;li&gt;Port mappings&lt;/li&gt;
&lt;li&gt;Connection strings&lt;/li&gt;
&lt;li&gt;Operational guidance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All values are generated using the parameters provided during plate generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Plates?
&lt;/h2&gt;

&lt;p&gt;Instead of copying Compose files between projects, teams can generate consistent infrastructure stacks from a controlled source.&lt;/p&gt;

&lt;p&gt;Benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Versioned infrastructure definitions&lt;/li&gt;
&lt;li&gt;Standardised health checks&lt;/li&gt;
&lt;li&gt;Consistent security settings&lt;/li&gt;
&lt;li&gt;Reusable configuration patterns&lt;/li&gt;
&lt;li&gt;Optional feature modules&lt;/li&gt;
&lt;li&gt;Built-in documentation generation&lt;/li&gt;
&lt;li&gt;Reduced setup time for new projects&lt;/li&gt;
&lt;li&gt;Easier maintenance across teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every generated stack follows the same design principles and can be reproduced at any time from its original plate version.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Collection
&lt;/h2&gt;

&lt;p&gt;The repository currently contains twenty Docker Compose plates organised into five categories.&lt;/p&gt;

&lt;p&gt;Each plate defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A service stack&lt;/li&gt;
&lt;li&gt;Schema-driven configuration&lt;/li&gt;
&lt;li&gt;Optional modules&lt;/li&gt;
&lt;li&gt;Generated documentation&lt;/li&gt;
&lt;li&gt;Environment templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each row in the collection documents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The plate slug&lt;/li&gt;
&lt;li&gt;The generated Docker Compose services&lt;/li&gt;
&lt;li&gt;Available optional modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows teams to quickly select the required infrastructure stack and generate a production-ready environment with a single command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database
&lt;/h2&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhl5tkzgxm6wm50yv3c86.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhl5tkzgxm6wm50yv3c86.png" alt="Database category showing PostgreSQL, MySQL, MariaDB, MongoDB and Redis Docker Compose plates and their optional modules" width="530" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmzdq20xhzqz85rtw16qj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmzdq20xhzqz85rtw16qj.png" alt="Backend category showing application platforms and workflow services with their supported dependencies and optional modules" width="585" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps
&lt;/h2&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhag6suc47u9rky094z8c.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhag6suc47u9rky094z8c.png" alt="DevOps category showing monitoring, observability, message broker and infrastructure related Docker Compose plates" width="799" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fal0b0xojcfm8sy6mq6mt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fal0b0xojcfm8sy6mq6mt.png" alt="Security category showing identity management, secret management and security-focused Docker Compose plates" width="492" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other
&lt;/h2&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg39qcjx8vv1954ieg8dy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg39qcjx8vv1954ieg8dy.png" alt="Additional utility and supporting Docker Compose plates available in the collection" width="492" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture and Composition
&lt;/h2&gt;

&lt;p&gt;The diagram below shows all twenty plates and the composition relationships between them. Solid arrows indicate a default-enabled composition. Dashed arrows indicate an optional module.&lt;/p&gt;

&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1eweqkn4aoog14h47565.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1eweqkn4aoog14h47565.png" alt="Architecture diagram showing all Docker Compose plates and their composition relationships, including optional and required dependencies between services" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Composition Works
&lt;/h2&gt;

&lt;p&gt;Many infrastructure stacks depend on other services. For example, Keycloak typically requires a PostgreSQL database.&lt;/p&gt;

&lt;p&gt;Instead of duplicating database definitions, kikplate supports &lt;strong&gt;plate composition&lt;/strong&gt;, allowing one plate to reuse templates from another plate.&lt;/p&gt;

&lt;p&gt;The Keycloak plate composes the PostgreSQL plate by referencing its templates directly in &lt;code&gt;plate.yaml&lt;/code&gt;.&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;modules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&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;pgadmin&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;false&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;docker-compose.yml&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/docker-compose-plates/keycloak/templates/docker-compose.yml.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.postgres.yml&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/docker-compose-plates/postgres/templates/docker-compose.yml.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.postgres.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;.env&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/docker-compose-plates/keycloak/templates/.env.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/docker-compose-plates/keycloak/templates/README.md.tmpl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;modules.postgres.enabled&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;, kikplate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetches the PostgreSQL template from the PostgreSQL plate branch.&lt;/li&gt;
&lt;li&gt;Renders it using the values provided to the Keycloak plate.&lt;/li&gt;
&lt;li&gt;Generates a dedicated &lt;code&gt;docker-compose.postgres.yml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Includes that generated Compose file in the final deployment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach enables reusable infrastructure building blocks without copying configuration between plates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shared Schema
&lt;/h2&gt;

&lt;p&gt;To ensure the PostgreSQL template always receives valid input values, the Keycloak plate includes all PostgreSQL-related variables in its own 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;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;keycloak&lt;/span&gt;

  &lt;span class="na"&gt;keycloakVersion&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;24.0"&lt;/span&gt;

  &lt;span class="na"&gt;postgresVersion&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16"&lt;/span&gt;

  &lt;span class="na"&gt;postgresPort&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;5432&lt;/span&gt;

  &lt;span class="na"&gt;timezone&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;UTC&lt;/span&gt;

  &lt;span class="na"&gt;sharedBuffers&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128MB"&lt;/span&gt;

  &lt;span class="na"&gt;maxConnections&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;100&lt;/span&gt;

  &lt;span class="na"&gt;pgadminVersion&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8"&lt;/span&gt;

  &lt;span class="na"&gt;pgadminPort&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;5050&lt;/span&gt;

  &lt;span class="na"&gt;pgadminEmail&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;admin@example.com&lt;/span&gt;

  &lt;span class="na"&gt;keycloakPort&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;keycloakLogLevel&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;INFO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because all required PostgreSQL variables are available in the schema, the PostgreSQL templates can be rendered independently without requiring any additional configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Compose Includes
&lt;/h2&gt;

&lt;p&gt;The Keycloak Compose template uses Docker Compose's &lt;code&gt;include&lt;/code&gt; capability to compose the generated PostgreSQL stack into the final deployment.&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;if .modules.postgres.enabled&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-compose.postgres.yml&lt;/span&gt;
&lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;keycloak&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;quay.io/keycloak/keycloak:{{ .keycloakVersion }}&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.projectName&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;-keycloak&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;

    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;KC_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="na"&gt;KC_DB_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdbc:postgresql://postgres:5432/keycloak&lt;/span&gt;
      &lt;span class="na"&gt;KC_DB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;KC_DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
      &lt;span class="na"&gt;KEYCLOAK_ADMIN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${KEYCLOAK_ADMIN}&lt;/span&gt;
      &lt;span class="na"&gt;KEYCLOAK_ADMIN_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${KEYCLOAK_ADMIN_PASSWORD}&lt;/span&gt;

    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.keycloakPort&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}:8080"&lt;/span&gt;

    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&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;service_healthy&lt;/span&gt;

    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kc_net&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db_net&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kc_net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When PostgreSQL is enabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker-compose.postgres.yml&lt;/code&gt; is generated.&lt;/li&gt;
&lt;li&gt;The Keycloak stack includes it automatically.&lt;/li&gt;
&lt;li&gt;The PostgreSQL service exposes the &lt;code&gt;db_net&lt;/code&gt; network.&lt;/li&gt;
&lt;li&gt;The Keycloak container joins &lt;code&gt;db_net&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Keycloak can connect to PostgreSQL using the hostname &lt;code&gt;postgres&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Startup order is controlled through health checks and &lt;code&gt;depends_on&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a loosely coupled but fully integrated deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generated Output
&lt;/h2&gt;

&lt;p&gt;Generating the Keycloak plate produces the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generated/
├── docker-compose.yml
├── docker-compose.postgres.yml
├── .env
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  docker-compose.yml
&lt;/h2&gt;

&lt;p&gt;Contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Keycloak service&lt;/li&gt;
&lt;li&gt;Compose include directives&lt;/li&gt;
&lt;li&gt;Keycloak-specific networking and configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  docker-compose.postgres.yml
&lt;/h2&gt;

&lt;p&gt;Contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL service&lt;/li&gt;
&lt;li&gt;Persistent volumes&lt;/li&gt;
&lt;li&gt;Health checks&lt;/li&gt;
&lt;li&gt;Logging configuration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;db_net&lt;/code&gt; network&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  .env
&lt;/h2&gt;

&lt;p&gt;Contains shared credentials used by both services.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_USER=app
POSTGRES_PASSWORD=changeme
POSTGRES_DB=keycloak

KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=changeme
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  README.md
&lt;/h2&gt;

&lt;p&gt;Contains deployment-specific documentation including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Startup instructions&lt;/li&gt;
&lt;li&gt;Access URLs&lt;/li&gt;
&lt;li&gt;Port mappings&lt;/li&gt;
&lt;li&gt;Login credentials guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Benefits of Composition
&lt;/h2&gt;

&lt;p&gt;Plate composition provides several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuse existing infrastructure definitions&lt;/li&gt;
&lt;li&gt;Eliminate configuration duplication&lt;/li&gt;
&lt;li&gt;Keep service definitions independent&lt;/li&gt;
&lt;li&gt;Share common variables across related stacks&lt;/li&gt;
&lt;li&gt;Generate modular Docker Compose deployments&lt;/li&gt;
&lt;li&gt;Simplify maintenance and versioning&lt;/li&gt;
&lt;li&gt;Allow optional dependencies through modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of embedding PostgreSQL directly into the Keycloak plate, the Keycloak plate composes the PostgreSQL plate as a reusable building block. This keeps both plates focused on a single responsibility while still allowing them to work together as a complete deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composition Examples
&lt;/h2&gt;

&lt;p&gt;The same composition pattern is used throughout the collection.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WordPress&lt;/strong&gt; → composes MySQL, optionally Redis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n&lt;/strong&gt; → composes PostgreSQL, optionally Redis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana and observability stacks&lt;/strong&gt; → optionally compose PostgreSQL as the backend database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each plate remains focused on a single responsibility while reusing infrastructure components from other plates where appropriate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generating a Plate
&lt;/h2&gt;

&lt;p&gt;The simplest generation flow uses interactive prompts and accepts default values.&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 kikplate-public/postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generate from a Values File
&lt;/h2&gt;

&lt;p&gt;To avoid prompts entirely, provide a values file.&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 kikplate-public/postgres &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every plate includes a &lt;code&gt;values.yaml&lt;/code&gt; file containing all schema variables with default values.&lt;/p&gt;

&lt;p&gt;Teams typically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate a values file.&lt;/li&gt;
&lt;li&gt;Customise it for their environment.&lt;/li&gt;
&lt;li&gt;Commit it into source control.&lt;/li&gt;
&lt;li&gt;Regenerate infrastructure at any time from the committed values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This makes infrastructure reproducible and eliminates manual configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Override Individual Values
&lt;/h2&gt;

&lt;p&gt;Specific values can be overridden directly on the command line.&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 kikplate-public/postgres &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;projectName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;myapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;postgresPort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5433
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Generate into a Specific Directory
&lt;/h2&gt;

&lt;p&gt;Generated files can be written to a dedicated location.&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 kikplate-public/postgres &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output-dir&lt;/span&gt; ./infra/postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Generate Directly to a Repository
&lt;/h2&gt;

&lt;p&gt;Generated output can also be pushed directly into a remote repository.&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 kikplate-public/postgres &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repo&lt;/span&gt; https://github.com/yourorg/infra.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Consistency Across Every Plate
&lt;/h2&gt;

&lt;p&gt;Regardless of the service being provisioned, every plate follows the same operational and security standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secrets Management
&lt;/h2&gt;

&lt;p&gt;No passwords or secrets are embedded in templates.&lt;/p&gt;

&lt;p&gt;Generated secrets are written to a separate &lt;code&gt;.env&lt;/code&gt; file with placeholder values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_PASSWORD=changeme
REDIS_PASSWORD=changeme
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Developers replace these values before starting the stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Health Checks
&lt;/h2&gt;

&lt;p&gt;Every stateful service defines a health check.&lt;/p&gt;

&lt;p&gt;Dependent services wait until dependencies become healthy before starting.&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;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&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;service_healthy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This guarantees a reliable startup sequence during:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Logging
&lt;/h2&gt;

&lt;p&gt;Every service uses the Docker &lt;code&gt;json-file&lt;/code&gt; logging driver.&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;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json-file&lt;/span&gt;
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;max-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10m"&lt;/span&gt;
    &lt;span class="na"&gt;max-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log rotation&lt;/li&gt;
&lt;li&gt;Predictable disk usage&lt;/li&gt;
&lt;li&gt;Consistent behaviour across stacks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Network Isolation
&lt;/h2&gt;

&lt;p&gt;Each plate defines its own named Docker bridge network.&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;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app_net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Services communicate only within their assigned network.&lt;/p&gt;

&lt;p&gt;When plates are composed together, the dependent service joins the required networks to enable controlled communication between components.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Options
&lt;/h2&gt;

&lt;p&gt;All containers run with:&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;security_opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;no-new-privileges:true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional Linux capabilities are not granted unless the application explicitly requires them.&lt;/p&gt;

&lt;p&gt;For example:&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;cap_add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IPC_LOCK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is included for Vault because its functionality depends on memory locking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Graceful Shutdown
&lt;/h2&gt;

&lt;p&gt;Every container defines a shutdown grace period.&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;stop_grace_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows databases, queues, and brokers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete pending writes&lt;/li&gt;
&lt;li&gt;Flush data safely&lt;/li&gt;
&lt;li&gt;Exit cleanly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;before container termination.&lt;/p&gt;




&lt;h2&gt;
  
  
  Official Images
&lt;/h2&gt;

&lt;p&gt;Every plate uses official vendor-maintained container images.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;postgres&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mysql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redis&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grafana&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;quay.io/keycloak/keycloak&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Images are version-pinned through schema defaults and can be overridden at generation time.&lt;/p&gt;

&lt;p&gt;No community-maintained wrappers or floating &lt;code&gt;latest&lt;/code&gt; tags are used.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Teams Use This
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Small Development Teams
&lt;/h2&gt;

&lt;p&gt;A backend team starts a new service and requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without automation, the team typically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copies an old &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adjusts service names.&lt;/li&gt;
&lt;li&gt;Changes ports.&lt;/li&gt;
&lt;li&gt;Updates image versions.&lt;/li&gt;
&lt;li&gt;Fixes broken health checks.&lt;/li&gt;
&lt;li&gt;Troubleshoots startup issues.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With kikplate:&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 kikplate-public/postgres &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; postgres-values.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output-dir&lt;/span&gt; ./infra/postgres

kik generate kikplate-public/redis &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; redis-values.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output-dir&lt;/span&gt; ./infra/redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two commands produce two standardised infrastructure stacks.&lt;/p&gt;

&lt;p&gt;The generated configurations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current&lt;/li&gt;
&lt;li&gt;Version-controlled&lt;/li&gt;
&lt;li&gt;Health-checked&lt;/li&gt;
&lt;li&gt;Secure by default&lt;/li&gt;
&lt;li&gt;Reproducible&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Platform Teams
&lt;/h2&gt;

&lt;p&gt;Platform engineering teams often need to standardise infrastructure across dozens of services.&lt;/p&gt;

&lt;p&gt;A common approach is to maintain approved values files.&lt;/p&gt;

&lt;p&gt;When a new service is created, developers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select an approved plate.&lt;/li&gt;
&lt;li&gt;Generate infrastructure using the approved values file.&lt;/li&gt;
&lt;li&gt;Commit the generated output alongside their application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures every service begins with infrastructure aligned to organisational standards.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updating Existing Deployments
&lt;/h2&gt;

&lt;p&gt;When a plate receives updates such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New image versions&lt;/li&gt;
&lt;li&gt;Security improvements&lt;/li&gt;
&lt;li&gt;Additional configuration options&lt;/li&gt;
&lt;li&gt;Operational enhancements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;teams simply regenerate the files.&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 kikplate-public/postgres &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated changes can be reviewed using normal source control workflows.&lt;/p&gt;

&lt;p&gt;The plate remains the single source of truth for infrastructure configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Structure
&lt;/h2&gt;

&lt;p&gt;The Docker Compose Plates collection is hosted at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kikplate/docker-compose-plates" rel="noopener noreferrer"&gt;Docker Compose Plates Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository uses a branch-per-plate model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Individual Plate Branches
&lt;/h2&gt;

&lt;p&gt;Each plate resides on its own branch.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres
redis
mysql
keycloak
wordpress
n8n
grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each branch contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plate.yaml
values.yaml
templates/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  plate.yaml
&lt;/h3&gt;

&lt;p&gt;Defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema&lt;/li&gt;
&lt;li&gt;Modules&lt;/li&gt;
&lt;li&gt;Template files&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  values.yaml
&lt;/h3&gt;

&lt;p&gt;Contains default values for all schema variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  templates/
&lt;/h3&gt;

&lt;p&gt;Contains the source templates that are rendered during generation.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;templates/
├── docker-compose.yml.tmpl
├── .env.tmpl
├── README.md.tmpl
└── additional configuration templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Main Branch
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; branch contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Guides&lt;/li&gt;
&lt;li&gt;The plate catalogue&lt;/li&gt;
&lt;li&gt;Repository metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It acts as the public entry point for the collection.&lt;/p&gt;




&lt;h2&gt;
  
  
  All Branch
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;all&lt;/code&gt; branch contains every plate as a subdirectory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;all/
├── postgres/
├── redis/
├── keycloak/
├── wordpress/
├── grafana/
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This branch exists primarily for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-plate development&lt;/li&gt;
&lt;li&gt;Local testing&lt;/li&gt;
&lt;li&gt;Refactoring shared functionality&lt;/li&gt;
&lt;li&gt;Reviewing the complete collection in a single working tree&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Docker Compose Plates turns infrastructure configuration from a copy-and-paste exercise into a repeatable generation process.&lt;/p&gt;

&lt;p&gt;By combining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typed schemas&lt;/li&gt;
&lt;li&gt;Versioned templates&lt;/li&gt;
&lt;li&gt;Optional modules&lt;/li&gt;
&lt;li&gt;Plate composition&lt;/li&gt;
&lt;li&gt;Standardised operational practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;teams can generate production-ready infrastructure stacks in seconds while maintaining consistency across every environment and every project.&lt;/p&gt;

</description>
      <category>boilerplate</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <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>
