Template System

Code generation with Handlebars templates

5 min read

Template System

Generate code using Handlebars (.hbs) templates linked to documentation.

Overview

The Template System allows you to:

  • Create reusable code templates with Handlebars syntax
  • Link templates to documentation for context-aware generation
  • Run templates via CLI or MCP for AI-assisted code generation
  • Preview output with dry-run before writing files

Template Structure

Templates live in .knowns/templates/:

.knowns/templates/
└── component/
    ├── _template.yaml    # Configuration file
    └── {{name}}.tsx.hbs  # Template file(s)

Configuration File (_template.yaml)

description: "React component generator"
doc: "patterns/component"          # Linked documentation
prompts:
  - variable: name
    message: "Component name?"
    default: "MyComponent"
  - variable: type
    message: "Component type?"
    options: ["page", "component", "layout"]
files:
  - template: "{{name}}.tsx.hbs"
    output: "src/components/{{name}}.tsx"
  - template: "{{name}}.test.tsx.hbs"
    output: "src/components/{{name}}.test.tsx"
    condition: "{{includeTests}}"

Template File (.hbs)

import React from 'react';
 
interface {{pascalCase name}}Props {
  children?: React.ReactNode;
}
 
export function {{pascalCase name}}({ children }: {{pascalCase name}}Props) {
  return (
    <div className="{{kebabCase name}}">
      {children}
    </div>
  );
}

CLI Commands

List Templates

knowns template list --plain

View Template Details

knowns template view component --plain
knowns template component --plain  # shorthand

Shows:

  • Description
  • Required variables (prompts)
  • Files that will be generated

Run Template (Dry Run)

Preview without writing files:

knowns template run component --dry-run

Run Template (Generate Files)

Interactive prompts will ask for variables:

knowns template run component

Create Template

knowns template create api-endpoint -d "REST API endpoint generator"

Handlebars Helpers

Case Transformations

HelperInputOutput
{{pascalCase name}}my-buttonMyButton
{{camelCase name}}my-buttonmyButton
{{kebabCase name}}MyButtonmy-button
{{snakeCase name}}MyButtonmy_button
{{upperCase name}}myButtonMYBUTTON
{{lowerCase name}}MyButtonmybutton

Conditionals

{{#if includeTests}}
import { render } from '@testing-library/react';
{{/if}}
 
{{#unless minimal}}
// Full implementation
{{/unless}}

Loops

{{#each fields}}
  {{this.name}}: {{this.type}};
{{/each}}

Comparisons

{{#eq type "page"}}
export default function {{name}}Page() {
{{/eq}}
 
{{#eq type "component"}}
export function {{name}}() {
{{/eq}}

Linking Documentation

Templates can reference documentation for AI context:

# _template.yaml
description: "API endpoint following our patterns"
doc: "patterns/api"  # @doc/patterns/api

When AI runs this template:

  1. Reads @doc/patterns/api for context
  2. Understands project conventions
  3. Generates code following patterns

Example: Full Template

_template.yaml

description: "Next.js API route handler"
doc: "patterns/api-routes"
prompts:
  - variable: name
    message: "Endpoint name (e.g., users, posts)?"
  - variable: methods
    message: "HTTP methods?"
    options: ["GET", "POST", "GET,POST", "GET,POST,PUT,DELETE"]
    default: "GET,POST"
files:
  - template: "route.ts.hbs"
    output: "src/app/api/{{kebabCase name}}/route.ts"

route.ts.hbs

import { NextRequest, NextResponse } from 'next/server';
 
{{#contains methods "GET"}}
export async function GET(request: NextRequest) {
  try {
    // TODO: Implement GET /api/{{kebabCase name}}
    return NextResponse.json({ message: 'Success' });
  } catch (error) {
    return NextResponse.json({ error: 'Failed' }, { status: 500 });
  }
}
{{/contains}}
 
{{#contains methods "POST"}}
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    // TODO: Implement POST /api/{{kebabCase name}}
    return NextResponse.json({ message: 'Created' }, { status: 201 });
  } catch (error) {
    return NextResponse.json({ error: 'Failed' }, { status: 500 });
  }
}
{{/contains}}

MCP Integration

Templates are available via MCP for AI assistants:

// List templates
mcp__knowns__list_templates({})
 
// Get template details
mcp__knowns__get_template({ "name": "component" })
 
// Run template (dry run)
mcp__knowns__run_template({
  "name": "component",
  "variables": { "name": "Button" },
  "dryRun": true
})
 
// Run template (generate files)
mcp__knowns__run_template({
  "name": "component",
  "variables": { "name": "Button" },
  "dryRun": false
})

Best Practices

Always link templates to relevant documentation:

doc: "patterns/component"

This helps AI understand context when generating code.

2. Use Meaningful Defaults

prompts:
  - variable: name
    message: "Component name?"
    default: "MyComponent"  # Sensible default

3. Include Dry Run in Workflow

Always preview before generating:

# Preview first
knowns template run component --var name=Header --dry-run
 
# Then generate
knowns template run component --var name=Header

4. Organize Templates by Domain

.knowns/templates/
├── components/
│   └── react-component/
├── api/
│   └── rest-endpoint/
└── tests/
    └── unit-test/

Importing Templates

Share templates across projects using the import system:

# Import from GitHub
knowns import github:myorg/templates --name my-templates
 
# Import from npm
knowns import npm:@myorg/templates --ref ^1.0.0
 
# Sync to get latest changes
knowns import sync my-templates
 
# List imported templates
knowns template list --plain

Imported templates are stored in .knowns/imports/<name>/templates/.

See Import System for full documentation on importing and syncing.

Supported AI Platforms

Templates can be used via CLI or MCP across multiple AI platforms:

PlatformSkillsMCP
Claude Code.claude/skills/Full
Antigravity.agent/skills/Full
Gemini CLI~/.gemini/commands/Full
Cursor.cursor/rules/Full
Windsurf.windsurfrulesLimited
Cline.clinerules/Full

Note: Claude Code and Antigravity use the same SKILL.md format - templates and skills are portable!