> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Build Kodexa Project Templates

> Hands-on guide to designing, building, and deploying effective Kodexa project templates that capture configurations, resources, and workflows for reuse.

This guide walks you through the practical aspects of building project templates in Kodexa. For detailed reference documentation on the complete structure and all available properties, see [Project Template Structure Reference](/concepts/project_template_structure).

## Table of Contents

1. [Quick Start](#quick-start)
2. [Design Principles](#design-principles)
3. [Building Your First Template](#building-your-first-template)
4. [Common Patterns](#common-patterns)
5. [Advanced Techniques](#advanced-techniques)
6. [Testing and Deployment](#testing-and-deployment)
7. [Troubleshooting](#troubleshooting)

***

## Quick Start

### What is a Project Template?

A project template is a blueprint that defines the complete structure of a Kodexa project. When a user creates a project from a template, Kodexa instantiates all the components defined in the template: stores, assistants, taxonomies, workspaces, and more.

### Minimum Viable Template

The simplest project template:

```yaml theme={null}
slug: my-first-template
orgSlug: my-org
version: 1.0.0
name: My First Template
type: projectTemplate
description: A simple starting point for document processing

stores:
  - slug: "documents"
    name: "Documents"
    description: "Document storage"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
```

Deploy this with:

```bash theme={null}
kdx deploy my-first-template.yaml
```

### Template Structure Overview

```yaml theme={null}
# Base metadata (required)
slug: unique-identifier
orgSlug: your-org
version: 1.0.0
name: Display Name
type: projectTemplate
description: What this template does

# Optional metadata
helpUrl: https://docs.example.com/template-guide

# Component collections (all optional)
stores: []           # Document and data repositories
assistants: []       # AI-powered automation
taxonomies: []       # Classification systems
dataForms: []        # Structured data entry
workspaces: []       # UI configurations
knowledgeSets: []    # Business rules and logic

# Status workflows (optional)
documentStatuses: [] # Document workflow states
taskStatuses: []     # Task workflow states
attributeStatuses: [] # Attribute workflow states

# Configuration (optional)
options: {}          # User-configurable settings
memory: {}           # UI state persistence
tags: []             # Template categorization
```

***

## Design Principles

### 1. Start with the User Journey

Before writing YAML, map out the user's workflow:

```text theme={null}
Document Upload → Automatic Processing → Review → Approval → Export
```

This journey might translate to:

* **Store**: Raw documents (upload destination)
* **Assistant**: PDF parser (automatic processing)
* **Workspace**: Review interface
* **Document Statuses**: New → Processing → Review → Approved
* **Data Form**: Manual corrections

### 2. Use Variable Substitution for Uniqueness

Always use `${project.id}` in slugs to ensure uniqueness:

```yaml theme={null}
stores:
  - slug: "${project.id}-documents"  # ✓ Unique per project
    # NOT:
  - slug: "documents"                 # ✗ Could conflict
```

**Available variables:**

| Variable          | Example              | Use Case             |
| ----------------- | -------------------- | -------------------- |
| `${project.id}`   | `abc-123-def-456`    | Unique identifiers   |
| `${project.name}` | `Invoice Processing` | Display names        |
| `${project.slug}` | `invoice-processing` | Human-readable IDs   |
| `${orgSlug}`      | `acme-corp`          | Organization context |

### 3. Separate Concerns by Store Purpose

```yaml theme={null}
stores:
  # Raw input
  - slug: "${project.id}-intake"
    storePurpose: OPERATIONAL
    description: "Documents awaiting processing"

  # Training data
  - slug: "${project.id}-training"
    storePurpose: TRAINING
    description: "Labeled documents for model training"

  # Final output
  - slug: "${project.id}-processed"
    storePurpose: OPERATIONAL
    description: "Successfully processed documents"
```

### 4. Build Incrementally

Start minimal and add complexity as needed:

1. **Phase 1**: Single store + basic workspace
2. **Phase 2**: Add assistant for automation
3. **Phase 3**: Add taxonomy for classification
4. **Phase 4**: Add data forms for manual entry
5. **Phase 5**: Add status workflows

***

## Building Your First Template

### Scenario: Invoice Processing System

Let's build a complete invoice processing template step by step.

#### Step 1: Define Base Metadata

```yaml theme={null}
slug: invoice-processing
orgSlug: acme-corp
version: 1.0.0
name: Invoice Processing Template
type: projectTemplate
description: |
  Automated invoice processing with OCR, data extraction, and validation.
  Suitable for accounts payable departments.

helpUrl: https://docs.acme-corp.com/invoice-processing

tags:
  - name: finance
  - name: automation
  - name: ocr
```

#### Step 2: Create Stores

```yaml theme={null}
stores:
  # Intake store for raw invoices
  - slug: "${project.id}-intake"
    name: "Invoice Intake"
    description: "Upload invoices here for processing"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
    deleteProtection: true
    highQualityPreview: true
    documentProperties:
      - name: vendor_name
        type: string
        label: Vendor Name
        description: Name of the invoice vendor
      - name: received_date
        type: date
        label: Date Received
        description: When the invoice was received
      - name: po_number
        type: string
        label: PO Number
        description: Purchase order number if applicable

  # Processed store for validated invoices
  - slug: "${project.id}-processed"
    name: "Processed Invoices"
    description: "Validated and approved invoices"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
    allowDataEditing: false

  # Exception store for problematic documents
  - slug: "${project.id}-exceptions"
    name: "Exception Queue"
    description: "Invoices requiring manual review"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
```

#### Step 3: Define Document Workflow

```yaml theme={null}
documentStatuses:
  - name: New
    slug: new
    color: "#6B7280"
    initial: true
    description: "Newly uploaded, awaiting processing"

  - name: Processing
    slug: processing
    color: "#3B82F6"
    description: "Currently being processed by assistant"

  - name: Extracted
    slug: extracted
    color: "#8B5CF6"
    description: "Data extracted, awaiting validation"

  - name: Validated
    slug: validated
    color: "#10B981"
    description: "Data validated and ready for approval"

  - name: Approved
    slug: approved
    color: "#059669"
    terminal: true
    description: "Invoice approved and exported"

  - name: Exception
    slug: exception
    color: "#EF4444"
    description: "Requires manual review"
```

#### Step 4: Create Assistant for Processing

```yaml theme={null}
assistants:
  - name: Invoice Data Extractor
    slug: invoice-extractor
    description: |
      Extracts structured data from invoice PDFs including:
      - Invoice number and date
      - Vendor information
      - Line items with quantities and prices
      - Total amounts
    assistantDefinitionRef: kodexa/pdf-invoice-extractor
    priorityHint: 10
    loggingEnabled: true

    # Connect to intake store
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-intake"
        subscription: "!hasMixins('processed')"

    # Grant access to stores
    stores:
      - "${orgSlug}/${project.id}-intake"
      - "${orgSlug}/${project.id}-processed"
      - "${orgSlug}/${project.id}-exceptions"

    # Configuration options
    options:
      use_ocr: true
      ocr_language: "eng"
      confidence_threshold: 0.85
      extract_line_items: true
      validate_totals: true
```

#### Step 5: Add Data Form for Manual Entry

```yaml theme={null}
dataForms:
  - slug: invoice-metadata
    name: Invoice Metadata Form
    description: Manual data entry for invoice information
    fields:
      - name: invoice_number
        type: text
        label: Invoice Number
        required: true
        validation:
          pattern: "^INV-\\d{6}$"
          message: "Must be in format INV-123456"

      - name: invoice_date
        type: date
        label: Invoice Date
        required: true

      - name: vendor_name
        type: text
        label: Vendor Name
        required: true

      - name: vendor_id
        type: text
        label: Vendor ID

      - name: total_amount
        type: number
        label: Total Amount
        required: true
        validation:
          min: 0
          message: "Amount must be positive"

      - name: currency
        type: select
        label: Currency
        required: true
        options:
          - value: USD
            label: US Dollar
          - value: EUR
            label: Euro
          - value: GBP
            label: British Pound

      - name: payment_terms
        type: select
        label: Payment Terms
        options:
          - value: net30
            label: Net 30
          - value: net60
            label: Net 60
          - value: due_on_receipt
            label: Due on Receipt

      - name: notes
        type: textarea
        label: Notes
        description: Additional notes or comments
```

#### Step 6: Create Taxonomy for Classification

```yaml theme={null}
taxonomies:
  - slug: invoice-categories
    name: Invoice Categories
    description: Classification of invoice types
    taxonomyType: CONTENT
    taxons:
      - name: Professional Services
        children:
          - name: Consulting
          - name: Legal
          - name: Accounting

      - name: Goods
        children:
          - name: Office Supplies
          - name: Equipment
          - name: Inventory

      - name: Utilities
        children:
          - name: Electric
          - name: Gas
          - name: Water
          - name: Internet/Telecom

      - name: Travel & Entertainment
        children:
          - name: Airfare
          - name: Hotel
          - name: Meals
          - name: Ground Transportation
```

#### Step 7: Configure Workspace

```yaml theme={null}
workspaces:
  - name: Invoice Processing Workspace
    slug: invoice-workspace
    description: Main interface for invoice review and approval
    workspaceStorage:
      availablePanels:
        documentStores: true
        dataForms: true
        taxonomies: true
        assistants: true
        exceptions: true
        auditEvents: true

      overview: |
        # Invoice Processing Workspace

        ## Quick Start
        1. Upload invoices to the **Invoice Intake** store
        2. The **Invoice Data Extractor** will automatically process them
        3. Review extracted data in **Processed Invoices**
        4. Use the **Invoice Metadata Form** for manual corrections
        5. Classify invoices using the **Invoice Categories** taxonomy

        ## Need Help?
        - [Processing Guidelines](https://docs.acme-corp.com/invoice-guidelines)
        - [Troubleshooting](https://docs.acme-corp.com/troubleshooting)
        - Contact: ap-team@acme-corp.com
```

#### Step 8: Add User Options

```yaml theme={null}
options:
  options:
    - name: auto_approve_threshold
      type: number
      label: Auto-Approve Threshold
      description: Automatically approve invoices under this amount
      default: 1000
      min: 0

    - name: require_po_matching
      type: boolean
      label: Require PO Matching
      description: Require purchase order number for all invoices
      default: true

    - name: notification_email
      type: string
      label: Notification Email
      description: Email address for exception notifications
      validation:
        pattern: "^[^@]+@[^@]+\\.[^@]+$"
        message: "Must be a valid email address"

    - name: retention_days
      type: number
      label: Document Retention (Days)
      description: How long to keep processed documents
      default: 2555
      min: 365
```

### Complete Template

Here's the full template assembled:

```yaml theme={null}
slug: invoice-processing
orgSlug: acme-corp
version: 1.0.0
name: Invoice Processing Template
type: projectTemplate
description: |
  Automated invoice processing with OCR, data extraction, and validation.
  Suitable for accounts payable departments.

helpUrl: https://docs.acme-corp.com/invoice-processing

tags:
  - name: finance
  - name: automation
  - name: ocr

stores:
  - slug: "${project.id}-intake"
    name: "Invoice Intake"
    description: "Upload invoices here for processing"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
    deleteProtection: true
    highQualityPreview: true
    documentProperties:
      - name: vendor_name
        type: string
        label: Vendor Name
      - name: received_date
        type: date
        label: Date Received
      - name: po_number
        type: string
        label: PO Number

  - slug: "${project.id}-processed"
    name: "Processed Invoices"
    description: "Validated and approved invoices"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL

  - slug: "${project.id}-exceptions"
    name: "Exception Queue"
    description: "Invoices requiring manual review"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL

documentStatuses:
  - name: New
    slug: new
    color: "#6B7280"
    initial: true
  - name: Processing
    slug: processing
    color: "#3B82F6"
  - name: Extracted
    slug: extracted
    color: "#8B5CF6"
  - name: Validated
    slug: validated
    color: "#10B981"
  - name: Approved
    slug: approved
    color: "#059669"
    terminal: true
  - name: Exception
    slug: exception
    color: "#EF4444"

assistants:
  - name: Invoice Data Extractor
    slug: invoice-extractor
    description: Extracts structured data from invoice PDFs
    assistantDefinitionRef: kodexa/pdf-invoice-extractor
    priorityHint: 10
    loggingEnabled: true
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-intake"
        subscription: "!hasMixins('processed')"
    stores:
      - "${orgSlug}/${project.id}-intake"
      - "${orgSlug}/${project.id}-processed"
      - "${orgSlug}/${project.id}-exceptions"
    options:
      use_ocr: true
      confidence_threshold: 0.85
      extract_line_items: true

dataForms:
  - slug: invoice-metadata
    name: Invoice Metadata Form
    description: Manual data entry for invoice information
    fields:
      - name: invoice_number
        type: text
        label: Invoice Number
        required: true
      - name: invoice_date
        type: date
        label: Invoice Date
        required: true
      - name: vendor_name
        type: text
        label: Vendor Name
        required: true
      - name: total_amount
        type: number
        label: Total Amount
        required: true

taxonomies:
  - slug: invoice-categories
    name: Invoice Categories
    description: Classification of invoice types
    taxonomyType: CONTENT
    taxons:
      - name: Professional Services
        children:
          - name: Consulting
          - name: Legal
      - name: Goods
        children:
          - name: Office Supplies
          - name: Equipment

workspaces:
  - name: Invoice Processing Workspace
    slug: invoice-workspace
    description: Main interface for invoice review and approval
    workspaceStorage:
      availablePanels:
        documentStores: true
        dataForms: true
        taxonomies: true
        assistants: true
        exceptions: true
      overview: |
        # Invoice Processing Workspace

        Upload invoices to get started.

options:
  options:
    - name: auto_approve_threshold
      type: number
      label: Auto-Approve Threshold
      default: 1000
    - name: require_po_matching
      type: boolean
      label: Require PO Matching
      default: true
```

***

## Common Patterns

### Pattern 1: Multi-Stage Processing Pipeline

Chain multiple assistants for sequential processing:

```yaml theme={null}
assistants:
  # Stage 1: Parse PDF
  - name: PDF Parser
    slug: pdf-parser
    assistantDefinitionRef: kodexa/pdf-parser
    priorityHint: 10
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-raw"

  # Stage 2: Extract structured data
  - name: Data Extractor
    slug: data-extractor
    assistantDefinitionRef: kodexa/data-extractor
    priorityHint: 5
    connections:
      - sourceType: CHANNEL
        # Triggers when pdf-parser completes
        subscription: "source == 'pdf-parser' && status == 'completed'"

  # Stage 3: Validate data
  - name: Data Validator
    slug: data-validator
    assistantDefinitionRef: kodexa/validator
    priorityHint: 3
    connections:
      - sourceType: CHANNEL
        subscription: "source == 'data-extractor' && status == 'completed'"
```

### Pattern 2: Conditional Processing with Subscriptions

Use subscription expressions to control when assistants trigger:

```yaml theme={null}
assistants:
  # Only process documents without spatial mixins
  - name: OCR Processor
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-documents"
        subscription: "!hasMixins('spatial')"

  # Only process documents above certain file size
  - name: Large Document Handler
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-documents"
        subscription: "fileSize > 10000000"

  # Only process specific document types
  - name: Invoice Processor
    connections:
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-documents"
        subscription: "metadata.document_type == 'invoice'"
```

### Pattern 3: Reference Existing Components

Reuse taxonomies and other components across templates:

```yaml theme={null}
taxonomies:
  # Reference an existing taxonomy
  - ref: "acme-corp/standard-document-types"

  # Or define a new one
  - slug: project-specific-categories
    name: Project Categories
    taxons:
      - name: Internal
      - name: External
```

### Pattern 4: Sample Data for Testing

Include sample files in stores:

```yaml theme={null}
stores:
  - slug: "${project.id}-samples"
    name: "Sample Documents"
    storeType: DOCUMENT
    storePurpose: OPERATIONAL
    files:
      - url: "https://example.com/samples/invoice-001.pdf"
        filename: "sample-invoice-001.pdf"
      - url: "https://example.com/samples/invoice-002.pdf"
        filename: "sample-invoice-002.pdf"
```

### Pattern 5: Pre-configured Workspaces

Create role-specific workspaces:

```yaml theme={null}
workspaces:
  # Workspace for data entry clerks
  - name: Data Entry Workspace
    slug: data-entry
    workspaceStorage:
      availablePanels:
        documentStores: true
        dataForms: true
      overview: "Upload and enter document data"

  # Workspace for reviewers
  - name: Review Workspace
    slug: review
    workspaceStorage:
      availablePanels:
        documentStores: true
        taxonomies: true
        exceptions: true
        auditEvents: true
      overview: "Review and approve processed documents"

  # Workspace for administrators
  - name: Admin Workspace
    slug: admin
    workspaceStorage:
      availablePanels:
        documentStores: true
        dataForms: true
        taxonomies: true
        assistants: true
        exceptions: true
        auditEvents: true
      overview: "Full administrative access"
```

### Pattern 6: Knowledge-Driven Processing

Use knowledge sets for rule-based automation:

```yaml theme={null}
knowledgeSets:
  - slug: invoice-routing-rules
    name: Invoice Routing Rules
    description: Route invoices based on business rules
    active: true
    features:
      - name: high_value
        type: boolean
        expression: "total_amount > 10000"

      - name: rush_vendor
        type: boolean
        expression: "vendor_name in ['Acme Supplies', 'FastShip Inc']"

      - name: missing_po
        type: boolean
        expression: "!hasField('po_number')"

    clauses:
      # Route to exceptions if high value AND missing PO
      - conditions:
          - feature: high_value
            value: true
          - feature: missing_po
            value: true
        action: route_to_exceptions

      # Fast-track rush vendors
      - conditions:
          - feature: rush_vendor
            value: true
        action: priority_processing
```

***

## Advanced Techniques

### Dynamic Store References

Build store references dynamically:

```yaml theme={null}
assistants:
  - name: Multi-Store Processor
    stores:
      - "${orgSlug}/${project.id}-store-1"
      - "${orgSlug}/${project.id}-store-2"
      - "${orgSlug}/${project.id}-store-3"
    connections:
      # Connect to all stores with pattern matching
      - sourceType: STORE
        sourceRef: "${orgSlug}/${project.id}-store-*"
```

### Scheduled Processing

Run assistants on a schedule:

```yaml theme={null}
assistants:
  - name: Nightly Report Generator
    slug: nightly-reports
    assistantDefinitionRef: acme/report-generator
    schedules:
      - cronExpression: "0 0 2 * * *"  # 2 AM daily
        timezone: "America/New_York"
      - cronExpression: "0 0 14 * * 1"  # 2 PM every Monday
        timezone: "America/New_York"
```

### Complex Form Validation

Add sophisticated validation to data forms:

```yaml theme={null}
dataForms:
  - slug: invoice-form
    fields:
      - name: invoice_number
        type: text
        required: true
        validation:
          pattern: "^INV-\\d{4}-\\d{6}$"
          message: "Format: INV-YYYY-NNNNNN"

      - name: invoice_date
        type: date
        required: true
        validation:
          # Can't be in the future
          maxDate: "today"
          # Must be within last year
          minDate: "today-365d"

      - name: total_amount
        type: number
        required: true
        validation:
          min: 0.01
          max: 1000000
          precision: 2  # Two decimal places
          message: "Amount must be between $0.01 and $1,000,000"

      - name: email
        type: text
        validation:
          pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
          message: "Must be a valid email address"
```

### Conditional Panel Visibility

Show/hide workspace panels based on project configuration:

```yaml theme={null}
workspaces:
  - name: Adaptive Workspace
    slug: adaptive
    workspaceStorage:
      availablePanels:
        documentStores: true
        dataForms: true
        # Only show taxonomies if enabled in options
        taxonomies: "${options.use_taxonomies}"
        # Only show assistants if user has admin role
        assistants: "${user.hasRole('admin')}"
        exceptions: true
```

### Multi-Level Taxonomies

Create deep hierarchical taxonomies:

```yaml theme={null}
taxonomies:
  - slug: document-classification
    name: Document Classification
    taxons:
      - name: Financial
        children:
          - name: Invoices
            children:
              - name: Accounts Payable
                children:
                  - name: Vendor Invoices
                  - name: Service Invoices
              - name: Accounts Receivable
                children:
                  - name: Customer Invoices
                  - name: Recurring Invoices
          - name: Receipts
            children:
              - name: Purchase Receipts
              - name: Payment Receipts

      - name: Contracts
        children:
          - name: Vendor Contracts
          - name: Customer Contracts
          - name: Employment Contracts
```

***

## Testing and Deployment

### Pre-Deployment Checklist

Before deploying your template:

* [ ] **YAML Syntax**: Validate YAML is well-formed
  ```bash theme={null}
  yamllint my-template.yaml
  ```

* [ ] **Variable Substitution**: Check all `${...}` variables are valid
  * `${project.id}`, `${project.name}`, `${project.slug}`, `${orgSlug}`

* [ ] **References**: Verify all component references exist
  * Assistant definitions: `orgSlug/assistant-name`
  * Store refs: `orgSlug/store-slug`
  * Taxonomy refs: `orgSlug/taxonomy-slug`

* [ ] **Slugs**: Ensure slugs are URL-safe (alphanumeric, hyphens, underscores only)

* [ ] **Required Fields**: All required properties are set
  * Stores: `slug`, `name`, `storeType`, `storePurpose`
  * Assistants: `name`, `slug`, `assistantDefinitionRef`

* [ ] **Colors**: Status colors are valid hex codes (`#RRGGBB`)

* [ ] **Workspace Panels**: At least one panel is enabled

* [ ] **Subscription Expressions**: Syntax is valid

### Testing Strategy

#### 1. Dry Run Validation

```bash theme={null}
# Validate template without deploying
kdx validate my-template.yaml
```

#### 2. Create Test Project

```bash theme={null}
# Deploy to test organization
kdx deploy my-template.yaml --org test-org

# Create project from template
kdx project create \
  --template acme-corp/invoice-processing \
  --name "Test Invoice Project"
```

#### 3. Test Each Component

**Test stores:**

```bash theme={null}
# Upload test document
kdx store upload ${project.id}-intake test-invoice.pdf

# Verify document appears
kdx store list ${project.id}-intake
```

**Test assistants:**

```bash theme={null}
# Check assistant created
kdx assistant list --project ${project.id}

# Monitor execution
kdx assistant logs invoice-extractor --project ${project.id}
```

**Test workspace:**

* Open workspace in UI
* Verify all panels appear correctly
* Test navigation between components

#### 4. Test Variable Substitution

Create a project and verify variables resolved correctly:

```bash theme={null}
# Get project details
kdx project get ${project.id}

# Check store slugs contain project ID
kdx store list --project ${project.id}
```

#### 5. Test Workflows

1. Upload document to intake store
2. Verify assistant triggers
3. Check document moves through statuses
4. Test data form submission
5. Verify taxonomy classification works

### Deployment Best Practices

#### Version Numbering

Use semantic versioning:

```yaml theme={null}
version: 1.0.0  # Major.Minor.Patch
```

* **Major**: Breaking changes (incompatible with previous version)
* **Minor**: New features (backward compatible)
* **Patch**: Bug fixes (backward compatible)

#### Deployment Command

```bash theme={null}
# Deploy new version
kdx deploy invoice-processing-template.yaml

# Deploy to specific organization
kdx deploy invoice-processing-template.yaml --org acme-corp

# Deploy with validation only
kdx deploy invoice-processing-template.yaml --validate-only
```

#### Rolling Updates

When updating templates:

1. **Test in staging**: Deploy to test org first
2. **Version increment**: Bump version number
3. **Document changes**: Update changelog/release notes
4. **Deploy to production**: Deploy to production org
5. **Monitor**: Check new projects create successfully

#### Rollback Strategy

Keep previous versions available:

```bash theme={null}
# List template versions
kdx template versions acme-corp/invoice-processing

# Create project from specific version
kdx project create \
  --template acme-corp/invoice-processing \
  --name "Rollback Test"
```

***

## Troubleshooting

### Common Issues and Solutions

#### Issue: "Variable substitution not working"

**Problem**: Variables like `${project.id}` appearing literally in created projects.

**Cause**: Variables only resolve during project creation, not in the template itself.

**Solution**:

* Variables are correct if they appear in the template YAML
* Check created project to see resolved values
* Use quotes around variable strings: `"${project.id}-store"`

#### Issue: "Assistant not triggering"

**Problem**: Assistant doesn't process documents added to store.

**Debug steps**:

```bash theme={null}
# Check assistant status
kdx assistant get invoice-extractor --project ${project.id}

# View assistant logs
kdx assistant logs invoice-extractor --project ${project.id}

# Check connections
kdx assistant connections invoice-extractor --project ${project.id}
```

**Common causes**:

1. **Wrong sourceRef**: Verify store reference is correct
   ```yaml theme={null}
   sourceRef: "${orgSlug}/${project.id}-intake"
   ```

2. **Subscription filter**: Check subscription expression
   ```yaml theme={null}
   subscription: "!hasMixins('processed')"
   ```
   * Remove temporarily to test without filter

3. **Store access**: Verify assistant has store in `stores` list
   ```yaml theme={null}
   stores:
     - "${orgSlug}/${project.id}-intake"
   ```

#### Issue: "Components not appearing in workspace"

**Problem**: Created stores/forms don't show in workspace.

**Cause**: Panels must be explicitly enabled.

**Solution**:

```yaml theme={null}
workspaces:
  - name: My Workspace
    workspaceStorage:
      availablePanels:
        documentStores: true    # Must be explicit
        dataForms: true         # Must be explicit
        # If missing, panel won't appear
```

#### Issue: "Reference not found"

**Problem**: `Component reference 'kodexa/my-assistant' not found`

**Debug**:

```bash theme={null}
# Check if assistant definition exists
kdx assistant-definition get kodexa/my-assistant

# List available versions
kdx assistant-definition versions kodexa/my-assistant
```

**Solutions**:

1. Deploy the referenced component first
2. Use correct version number
3. Check organization slug is correct

#### Issue: "Invalid subscription expression"

**Problem**: `Subscription expression syntax error`

**Valid expression examples**:

```yaml theme={null}
# Boolean checks
subscription: "!hasMixins('processed')"
subscription: "metadata.document_type == 'invoice'"

# Numeric comparisons
subscription: "fileSize > 1000000"
subscription: "confidence >= 0.85"

# String matching
subscription: "filename contains 'invoice'"
subscription: "status == 'completed'"

# Logical operators
subscription: "status == 'completed' && confidence > 0.9"
subscription: "type == 'invoice' || type == 'receipt'"
```

#### Issue: "Slug validation error"

**Problem**: `Invalid slug format`

**Requirements**:

* Only alphanumeric, hyphens, underscores
* No spaces or special characters
* Must start with letter or number

**Examples**:

```yaml theme={null}
slug: "my-template"           # ✓ Valid
slug: "my_template_v2"        # ✓ Valid
slug: "mytemplate123"         # ✓ Valid
slug: "my template"           # ✗ Invalid (space)
slug: "my-template!"          # ✗ Invalid (!)
slug: "-my-template"          # ✗ Invalid (starts with -)
```

#### Issue: "Options not appearing in UI"

**Problem**: Defined options don't show when creating project.

**Solution**: Check the nested `options` structure:

```yaml theme={null}
options:
  options:    # Yes, it's options/options
    - name: use_ocr
      type: boolean
      label: Use OCR
```

#### Issue: "Files not uploading to store"

**Problem**: Files defined in `files` list don't appear in created store.

**Debug**:

```yaml theme={null}
stores:
  - slug: "${project.id}-samples"
    files:
      - url: "https://example.com/sample.pdf"
        filename: "sample.pdf"
```

**Common causes**:

1. URL not accessible (401, 404)
2. File too large
3. Invalid filename

**Check logs**:

```bash theme={null}
kdx project logs ${project.id} --filter "file upload"
```

### Getting Help

#### Documentation Resources

* [Project Template Structure Reference](/concepts/project_template_structure) - Complete property reference
* [Project Templates Overview](/concepts/project_templates) - Conceptual overview
* [Assistant Configuration](/concepts/defining_an_assistant) - Assistant setup
* [Working with Stores](/concepts/storage) - Store configuration

#### API Reference

* [Create Project Template API](/api-reference/projects/get-projects-id-create-project-template-request)
* [Available Templates API](/api-reference/organizations/get-organizations-id-available-project-templates)

#### Support Channels

* **Documentation**: [developer.kodexa.ai](https://developer.kodexa.ai)
* **Support Email**: [support@kodexa.com](mailto:support@kodexa.com)
* **Community**: Kodexa Community Forums

***

## Summary

### Key Takeaways

1. **Start Simple**: Begin with minimal viable template, add complexity incrementally
2. **Use Variables**: Always use `${project.id}` for uniqueness
3. **Test Thoroughly**: Validate, create test project, verify each component
4. **Document Well**: Provide helpful descriptions and workspace overviews
5. **Version Carefully**: Use semantic versioning, maintain backward compatibility

### Next Steps

1. **Review Reference**: Read the [complete structure reference](/concepts/project_template_structure)
2. **Explore Examples**: Check existing templates in your organization
3. **Build Your Template**: Start with the quick start example and customize
4. **Test and Deploy**: Follow the testing checklist before production deployment
5. **Iterate**: Gather user feedback and improve your template over time

### Template Development Workflow

```text theme={null}
Design → Build → Validate → Test → Deploy → Monitor → Iterate
  ↑                                                      ↓
  └──────────────────────────────────────────────────────┘
```

Happy template building!
