Skip to main content
The template.* configuration file defines metadata and variables for a code generation template. This file must exist at the root of each template folder.

Configuration File

Location: <template-folder>/template.yml or <template-folder>/template.json Type: TemplateConfig Required: Yes, for each template

Schema

Core Settings

title
string
required
Human-readable title displayed during template generation.
title: 'React Component'
description
string
required
Description of what the template scaffolds and its purpose.
description: |
  Scaffolds a new React component with TypeScript,
  including component file, styles, and tests.
id
string
Overrides the template identifier (defaults to folder name).Must be unique across all template locations.
id: 'react-component'
Added in v1.23.0
destination
string
Pre-configured destination path for generation.
  • Prefixed with /: Relative from workspace root
  • No prefix: Relative from current working directory
Supports variable interpolation:
destination: 'packages/[name]'
# Or from workspace root
destination: '/apps/[name]'
Added in v1.19.0
extends
string | string[]
One or many templates to extend. Deeply inherits files and variables.
extends: 'base'
# Or multiple
extends:
  - 'base'
  - 'configs'
Added in v1.19.0

Variables

variables
object
Map of variable names to variable configurations.Variables are interpolated into template files and paths using Tera syntax.
variables:
  name:
    type: 'string'
    prompt: 'Component name?'
    required: true
  
  style:
    type: 'enum'
    values: ['css', 'scss', 'styled-components']
    default: 'css'
    prompt: 'Style approach?'
Each variable requires a type field with additional type-specific configuration.

Variable Types

String Variables

type
'string'
required
String variable type.
variables:
  name:
    type: 'string'
    default: ''
    prompt: 'Name?'
    required: true

Number Variables

type
'number'
required
Numeric variable type (integers only, no floats).
variables:
  port:
    type: 'number'
    default: 3000
    prompt: 'Port number?'
Same properties as string variables with default: number.

Boolean Variables

type
'boolean'
required
Boolean variable type.
variables:
  includeTests:
    type: 'boolean'
    default: true
    prompt: 'Include tests?'
Same properties as string variables with default: boolean.

Array Variables

type
'array'
required
Array variable type. Values must be JSON-compatible.
variables:
  features:
    type: 'array'
    default: ['auth', 'api']
    prompt: 'Features (JSON array)?'
Same properties as string variables with default: array.When prompting, users must provide valid JSON:
moon generate component --features '["routing","state"]'

Object Variables

type
'object'
required
Object variable type. Values must be JSON-compatible.
variables:
  config:
    type: 'object'
    default:
      enabled: true
      timeout: 5000
    prompt: 'Config (JSON object)?'
Same properties as string variables with default: object.

Enum Variables

type
'enum'
required
Enumerable string values with single or multiple selection.
variables:
  style:
    type: 'enum'
    values: ['css', 'scss', 'styled']
    default: 'css'
    prompt: 'Style approach?'
  
  frameworks:
    type: 'enum'
    values:
      - value: 'react'
        label: 'React ⚛️'
      - value: 'vue'
        label: 'Vue.js'
    default: ['react']
    multiple: true
    prompt: 'Frameworks?'

Frontmatter

Template files can include frontmatter to control generation behavior:
to
string
Custom output path relative to destination.Supports variable interpolation and Tera filters:
{% set component_name = name | pascal_case %}
---
to: components/{{ component_name }}.tsx
---

export function {{ component_name }}() {
  return <div />;
}
skip
boolean
Conditionally skip generating this file.
---
skip: {{ includeTests == false }}
---

test('example', () => {});
force
boolean
Always overwrite existing files without prompting.
---
force: true
---

// Always regenerate this file

Variable Interpolation

Variables are accessible in template files using Tera syntax:

Basic Usage

Component.tsx
export function {{ name | pascal_case }}(props: Props) {
  return (
    <div className="{{ name | kebab_case }}">
      {props.children}
    </div>
  );
}

Conditionals

{% if includeTests %}
import { render } from '@testing-library/react';
{% endif %}

export function {{ name }}() {
  // ...
}

Loops

{% for feature in features %}
import { {{ feature | pascal_case }} } from './features';
{% endfor %}

Filters

Tera provides built-in filters for transforming variables:
  • {{ name | lower }} - lowercase
  • {{ name | upper }} - UPPERCASE
  • {{ name | capitalize }} - Capitalize
  • {{ name | pascal_case }} - PascalCase
  • {{ name | camel_case }} - camelCase
  • {{ name | snake_case }} - snake_case
  • {{ name | kebab_case }} - kebab-case

Complete Example

templates/react-component/template.yml
id: 'react-component'
title: 'React Component'
description: |
  Scaffolds a new React component with TypeScript support,
  including the component file, styles, tests, and story.

destination: 'src/components/[name]'

variables:
  name:
    type: 'string'
    prompt: 'Component name?'
    required: true
    order: 1
  
  style:
    type: 'enum'
    values:
      - value: 'css'
        label: 'CSS Modules'
      - value: 'scss'
        label: 'SCSS Modules'
      - value: 'styled'
        label: 'Styled Components'
    default: 'css'
    prompt: 'Style approach?'
    order: 2
  
  includeStory:
    type: 'boolean'
    default: true
    prompt: 'Include Storybook story?'
    order: 3
  
  includeTests:
    type: 'boolean'
    default: true
    prompt: 'Include tests?'
    order: 4
  
  export:
    type: 'enum'
    values: ['named', 'default']
    default: 'named'
    prompt: 'Export type?'
    order: 5
templates/react-component/Component.tsx
{% set component_name = name | pascal_case %}
---
to: {{ component_name }}.tsx
---
import React from 'react';
{% if style == 'styled' %}
import styled from 'styled-components';
{% else %}
import styles from './{{ component_name }}.module.{{ style }}';
{% endif %}

interface {{ component_name }}Props {
  children?: React.ReactNode;
}

{% if export == 'default' %}
export default function {{ component_name }}(props: {{ component_name }}Props) {
{% else %}
export function {{ component_name }}(props: {{ component_name }}Props) {
{% endif %}
  return (
    <div className={styles.root}>
      {props.children}
    </div>
  );
}
templates/react-component/Component.test.tsx
{% set component_name = name | pascal_case %}
---
skip: {{ includeTests == false }}
to: {{ component_name }}.test.tsx
---
import { render } from '@testing-library/react';
import { {{ component_name }} } from './{{ component_name }}';

describe('{{ component_name }}', () => {
  it('renders', () => {
    const { container } = render(<{{ component_name }} />);
    expect(container).toBeTruthy();
  });
});

Usage

Generate from template:
# Interactive prompts
moon generate react-component

# With defaults
moon generate react-component --defaults

# With variable overrides
moon generate react-component \
  --name Button \
  --style scss \
  --includeTests false

# Custom destination
moon generate react-component packages/ui

Build docs developers (and LLMs) love