Skip to content

Template System

PUPT uses Handlebars as its template engine, enhanced with custom helpers for collecting user input and accessing system information. This powerful combination enables you to create dynamic, reusable prompt templates.

Prompt File Structure

A prompt file consists of two main parts:

  1. Frontmatter (optional): YAML metadata between --- markers
  2. Template Content: Markdown with Handlebars expressions
markdown
---
title: Example Prompt
tags: [example, demo]
variables:
  - name: projectName
    type: input
    message: "What's your project name?"
    default: "my-project"
---

# Project: {{projectName}}

Your template content here...

Frontmatter Reference

title

  • Type: string
  • Description: Display name for the prompt
  • Default: Filename without extension

tags

  • Type: string[]
  • Description: Tags for categorization and search
  • Default: []

variables

  • Type: object[]
  • Description: Pre-defined variables with validation
  • Properties:
    • name (required): Variable identifier
    • type: Input type (see Input Helpers)
    • message: Prompt message
    • default: Default value
    • choices: Options for select/multiselect
    • validate: Regex pattern for validation
    • required: Whether input is required
    • basePath: Base directory for file inputs
    • filter: File pattern filter
    • multiline: Enable multiline for input type

Example with All Properties

yaml
---
title: Advanced Example
tags: [advanced, complete]
variables:
  - name: componentName
    type: input
    message: "Component name:"
    default: "MyComponent"
    validate: "^[A-Z][a-zA-Z0-9]*$"
    required: true
    
  - name: framework
    type: select
    message: "Choose framework:"
    choices: ["React", "Vue", "Angular", "Svelte"]
    default: "React"
    
  - name: features
    type: multiselect
    message: "Select features:"
    choices: ["TypeScript", "Testing", "Storybook", "CSS Modules"]
    
  - name: description
    type: editor
    message: "Component description:"
    multiline: true
    
  - name: configFile
    type: file
    message: "Configuration file:"
    basePath: "./"
    filter: "*.{json,yaml,yml}"
---

Input Helpers

Input helpers are Handlebars helpers that collect information from users interactively. They can be used inline in templates or pre-defined in frontmatter.

{{input}}

Collect single-line text input.

handlebars
{{input "variableName" "Optional prompt message"}}

Options via frontmatter:

  • default: Default value
  • validate: Regex pattern for validation
  • required: Make input mandatory

Example:

handlebars
Project name: {{input "projectName" "What's your project name?"}}
Description: {{input "description"}}

{{select}}

Present a single-choice selection.

handlebars
{{select "variableName" "Optional prompt message"}}

Options via frontmatter:

  • choices: Array of options (required)
  • default: Default selection

Example:

yaml
variables:
  - name: language
    type: select
    message: "Programming language:"
    choices: ["JavaScript", "TypeScript", "Python", "Go"]
    default: "TypeScript"

{{multiselect}}

Allow multiple selections from a list.

handlebars
{{multiselect "variableName" "Optional prompt message"}}

Returns: Comma-separated string of selections

Example:

handlebars
Features to include: {{multiselect "features" "Select features:"}}

{{confirm}}

Ask a yes/no question.

handlebars
{{confirm "variableName" "Optional prompt message"}}

Returns: "true" or "false"

Example:

handlebars
{{#if (confirm "includeTests" "Include unit tests?")}}
Generate comprehensive unit tests...
{{/if}}

{{editor}}

Open the system editor for multi-line input.

handlebars
{{editor "variableName" "Optional prompt message"}}

Features:

  • Opens default editor ($EDITOR or $VISUAL)
  • Supports multi-line content
  • Preserves formatting

Example:

handlebars
## Detailed Requirements

{{editor "requirements" "Enter detailed requirements:"}}

{{password}}

Collect sensitive input with masked display.

handlebars
{{password "variableName" "Optional prompt message"}}

Features:

  • Input is masked during entry
  • Values are masked in history
  • Not shown in debug output

Example:

handlebars
API_KEY={{password "apiKey" "Enter your API key:"}}

{{file}}

Interactive file path selection with tab completion.

handlebars
{{file "variableName" "Optional prompt message"}}

Options via frontmatter:

  • basePath: Starting directory
  • filter: File pattern (glob)

Features:

  • Tab completion
  • Home directory expansion (~)
  • Real-time filtering

Example:

yaml
variables:
  - name: sourceFile
    type: file
    message: "Select source file:"
    basePath: "./src"
    filter: "*.{js,ts}"

{{reviewFile}}

Select a file for automatic review after execution.

handlebars
{{reviewFile "variableName" "Optional prompt message"}}

Features:

  • Same as {{file}} helper
  • File is automatically reviewed post-execution
  • Useful for analyzing generated outputs

Example:

handlebars
Output file: {{reviewFile "output" "File to review after generation:"}}

Static Helpers

Static helpers provide system information and utilities. They're evaluated when the template is processed.

Date and Time

  • {{date}} - Current date (e.g., "12/25/2024")
  • {{time}} - Current time (e.g., "2:30:45 PM")
  • {{datetime}} - Date and time combined
  • {{timestamp}} - Unix timestamp in milliseconds
  • {{isoDate}} - ISO 8601 date format

System Information

  • {{username}} - Current system username
  • {{hostname}} - Machine hostname
  • {{cwd}} - Current working directory
  • {{platform}} - Operating system platform
  • {{arch}} - System architecture

Utilities

  • {{uuid}} - Generate a UUID v4
  • {{random min max}} - Random number in range
  • {{env "VARIABLE"}} - Environment variable value

Examples:

handlebars
Generated by {{username}} on {{hostname}}
Date: {{isoDate}}
Request ID: {{uuid}}
Port: {{random 3000 9999}}
Home: {{env "HOME"}}

Conditional Logic

Use Handlebars built-in helpers for conditional rendering:

{{#if}}

handlebars
{{#if includeDocumentation}}
## Documentation

Please include comprehensive documentation...
{{/if}}

{{#unless}}

handlebars
{{#unless skipTests}}
Include unit tests for all functions.
{{/unless}}

{{#each}}

handlebars
{{#each selectedFeatures}}
- Implement {{this}} support
{{/each}}

Advanced Features

Variable Caching

Variables are cached after first use:

handlebars
Project: {{input "project"}}
...
// Later in the same template
Working on {{project}} // Uses cached value

Custom Helpers

Register custom helpers via configuration:

javascript
// In .pt-config.js
module.exports = {
  helpers: {
    uppercase: {
      type: 'inline',
      value: '{{uppercase text}}'
    }
  }
}
javascript
// helpers/custom.js
export default function(handlebars) {
  handlebars.registerHelper('uppercase', (text) => {
    return text.toUpperCase();
  });
}

Partials

Define reusable template fragments:

json
{
  "helpers": {
    "header": {
      "type": "file",
      "path": "./partials/header.md"
    }
  }
}

Usage:

handlebars
{{> header}}

Your content here...

Escaping

To output literal Handlebars syntax:

handlebars
{{escaped}}{{escaped}}
{{{{raw}}}}      → Start raw block
  {{literal}}{{literal}}
{{{{/raw}}}}     → End raw block

Best Practices

  1. Use Frontmatter Variables: Define variables upfront for better documentation
  2. Provide Defaults: Always include sensible defaults
  3. Validate Input: Use regex patterns to ensure valid input
  4. Group Related Inputs: Collect related information together
  5. Use Descriptive Names: Make variable names self-documenting
  6. Add Comments: Document complex template logic

Complete Example

markdown
---
title: React Component Generator
tags: [react, component, generator]
variables:
  - name: componentName
    type: input
    message: "Component name:"
    validate: "^[A-Z][a-zA-Z0-9]*$"
    default: "MyComponent"
    
  - name: componentType
    type: select
    message: "Component type:"
    choices: ["Functional", "Class"]
    default: "Functional"
    
  - name: features
    type: multiselect
    message: "Include features:"
    choices: ["PropTypes", "State", "Hooks", "Tests", "Storybook"]
    
  - name: styleFile
    type: file
    message: "Style file to import:"
    basePath: "./src/styles"
    filter: "*.{css,scss,less}"
---

# Generate React Component: {{componentName}}

Create a new {{componentType}} React component with the following specifications:

## Component Details
- **Name**: {{componentName}}
- **Type**: {{componentType}} Component
- **Features**: {{features}}
- **Style Import**: {{styleFile}}

## Requirements

1. Create the component file at `src/components/{{componentName}}/{{componentName}}.jsx`
2. Follow React best practices and conventions
3. Include proper error boundaries

{{#if (includes features "PropTypes")}}
## PropTypes
Define comprehensive PropTypes for all props with appropriate validations.
{{/if}}

{{#if (includes features "Tests")}}
## Testing
Create unit tests using Jest and React Testing Library:
- Test all props variations
- Test user interactions
- Achieve >90% coverage
{{/if}}

{{#if (includes features "Storybook")}}
## Storybook Stories
Create stories showcasing:
- Default state
- All prop variations
- Edge cases
- Interactive examples
{{/if}}

---
Generated by {{username}} on {{date}} at {{time}}

This example demonstrates:

  • Variable definition with validation
  • Conditional sections based on user input
  • System information integration
  • Clear structure and requirements

Released under the MIT License.