# Build System Reference

Complete guide to the Pencil build system for component linking and monolithic builds.

## Overview

The build system enables:
- **Component Linking**: Reference components across files
- **Monolithic Builds**: Merge all pages + components into one file
- **Standard Builds**: Inject components into individual pages
- **Validation**: Ensure output structure is valid

## Configuration

### pencil.config.json

Create in project root:

```json
{
  "version": "1.0",
  "sourceDir": "src",
  "buildDir": "build",
  "componentLibrary": "src/components/ui-kit.pen",
  "buildOptions": {
    "minify": false,
    "validateAfterBuild": true,
    "preserveComments": true
  }
}
```

| Field | Description |
|-------|-------------|
| `sourceDir` | Source files directory |
| `buildDir` | Build output directory |
| `componentLibrary` | Path to component library .pen file |
| `minify` | Minify JSON output |
| `validateAfterBuild` | Validate JSON after build |
| `preserveComments` | Keep JSON comments |

## Build Modes

### Monolithic Build ⭐ (Recommended)

Merges all pages + component library into one file.

**Commands:**
```bash
python3 scripts/build.py --monolithic
python3 scripts/build.py -m
python3 scripts/build.py --mode monolithic

# Custom output name
python3 scripts/build.py -m --output myDesign.pen
```

**Output:**
- **File**: `tPOS.pen` (project root)
- **Contains**: All pages + component library as separate frames
- **Size**: ~326KB (example)
- **Use case**: Opening complete design, sharing, archiving

**Example structure:**
```json
{
  "version": "2.6",
  "children": [
    {
      "type": "frame",
      "name": "Component Library",
      "children": [ /* All reusable components */ ]
    },
    {
      "type": "frame",
      "name": "Desktop Home Page",
      "children": [ /* Page content */ ]
    },
    {
      "type": "frame",
      "name": "Mobile Home Page",
      "children": [ /* Page content */ ]
    }
  ],
  "variables": { /* Design tokens */ }
}
```

### Component Library Build (Atomic Design)

Merges distributed atomic components into a single library file.

**Command:**
```bash
python3 scripts/build.py --library
python3 scripts/build.py -l
```

**Output:**
- **File**: `src/components/ui-kit.pen` (or configured path)
- **Contains**: All atoms, molecules, organisms merged into one file
- **Use case**: Generating the library to use during page design

### Standard Build

Builds individual pages with component injection.

**Command:**
```bash
python3 scripts/build.py
python3 scripts/build.py --mode standard
```

**Output:**
- **Directory**: `build/`
- **Files**: Separate `.pen` files with injected components
- **Use case**: Development workflow, testing component refs

**Example:**
```
build/
├── desktop-home.pen    # With injected components
├── mobile-home.pen     # With injected components
└── tablet-home.pen     # With injected components
```

## Build Process

### What the Build Script Does

1. **Load Component Library**: Read `ui-kit.pen`
2. **Extract Components**: Find all `reusable: true` components
3. **Extract Variables**: Get design tokens
4. **Find Component Refs**: Search for `component_ref` types in pages
5. **Resolve Paths**: Match `ui-kit#Button/Primary` to actual component
6. **Inject Components**: Add component definitions to pages
7. **Convert Refs**: Transform `component_ref` → `ref` with proper IDs
8. **Validate**: Check output structure

### Transformation Example

**Before build (source file):**
```json
{
  "type": "component_ref",
  "component": "ui-kit#Button/Primary",
  "name": "submitButton",
  "overrides": {
    "label_id": {
      "content": "Submit"
    }
  }
}
```

**After build (output file):**

Step 1: Component injected at top of children array
```json
{
  "type": "frame",
  "id": "abc123",
  "name": "Button/Primary",
  "reusable": true,
  "children": [
    {
      "type": "text",
      "id": "label_id",
      "content": "Button"
    }
  ]
}
```

Step 2: Reference converted
```json
{
  "type": "ref",
  "ref": "abc123",
  "name": "submitButton",
  "descendants": {
    "label_id": {
      "content": "Submit"
    }
  }
}
```

## Project Structure

### Recommended Structure

```
project-name/
├── src/
│   ├── components/
│   │   └── ui-kit.pen           # Component library + design tokens
│   └── pages/
│       ├── desktop-home.pen     # Desktop (1440px)
│       ├── mobile-home.pen      # Mobile (390px)
│       └── tablet-home.pen      # Tablet (768px)
├── build/                       # Standard build output (gitignore)
│   ├── desktop-home.pen         # With injected components
│   └── ...
├── scripts/
│   └── build.py                 # Build script
├── pencil.config.json           # Build configuration
├── tPOS.pen                     # Monolithic build output
└── USAGE_GUIDE.md               # Documentation
```

### Atomic Design Structure

For enterprise-scale UI Kits:

```
project-name/
├── src/
│   ├── foundations/
│   │   └── design-tokens.pen           # Design system variables
│   ├── atoms/                          # Smallest building blocks
│   │   ├── buttons.pen
│   │   ├── inputs.pen
│   │   └── badges.pen
│   ├── molecules/                      # Combinations of atoms
│   │   ├── form-fields.pen
│   │   └── search-bar.pen
│   ├── organisms/                      # Complex UI sections
│   │   ├── cards.pen
│   │   └── navigation.pen
│   └── pages/                          # Complete pages
│       ├── desktop-home.pen
│       └── mobile-home.pen
├── build/
├── scripts/
│   └── build.py
├── pencil.config.json
└── tPOS.pen
```

## Build Commands Reference

### Basic Commands

```bash
# Help
python3 scripts/build.py --help

# Monolithic build
python3 scripts/build.py -m

# Standard build
python3 scripts/build.py

# Custom output
python3 scripts/build.py -m --output custom.pen
```

### Validation Commands

```bash
# Validate JSON
jq empty tPOS.pen && echo "✅ Valid JSON"

# Check structure
jq '{version, childrenCount: (.children | length)}' tPOS.pen

# List frame names
jq '[.children[].name]' tPOS.pen

# Extract design tokens
jq '.variables' tPOS.pen

# Count components
jq '[.children[0].children[] | select(.reusable == true)] | length' tPOS.pen
```

## Workflows

### Atomic Design Workflow (Recommended)

```markdown
1. Layout & Components:
   - Update atoms/molecules in `src/atoms/` etc.
   - Run `python3 scripts/build.py --library` to update component library

2. Page Design:
   - Open `src/pages/desktop-home.pen`
   - Use components from the generated `src/components/ui-kit.pen`

3. Production Build:
   - Run `python3 scripts/build.py -m`
   - Output `tPOS.pen` contains everything
```

### Legacy/Mockup Workflow

```markdown
1. Design in modular files:
   - Edit components in `src/components/ui-kit.pen`
   - Edit pages in `src/pages/*.pen`
   - Use `component_ref` to reference components

2. Build for testing:
   python3 scripts/build.py  # Standard build
   # Open files in build/ to test

3. Build for production:
   python3 scripts/build.py -m  # Monolithic
   # Share tPOS.pen with team/clients

4. Convert to code:
   # Use agent to convert tPOS.pen to HTML/CSS/React/Blazor
```

### Component Library Updates

```markdown
1. Update component in ui-kit.pen
2. Save file
3. Rebuild all pages:
   python3 scripts/build.py -m
4. Test in Pencil app
5. If OK, commit changes
```

### Adding New Components

```markdown
1. Open ui-kit.pen in Pencil
2. Create component with:
   - Unique ID
   - Descriptive name (e.g., "Button/Secondary")
   - `reusable: true`
3. Save file
4. Use in pages with component_ref:
   {
     "type": "component_ref",
     "component": "ui-kit#Button/Secondary"
   }
5. Build and test
```

## Best Practices

### 1. Component References

```markdown
✅ DO: Use component_ref in source files
❌ DON'T: Hardcode components into pages

✅ DO: Keep components in ui-kit.pen
❌ DON'T: Duplicate components across files
```

### 2. Build Before Testing

```markdown
✅ DO: Build before opening in Pencil
❌ DON'T: Open source files directly

# Correct workflow:
python3 scripts/build.py -m
open tPOS.pen

# Component refs will be resolved ✅
```

### 3. Version Control

```markdown
✅ DO: Commit source files (src/)
✅ DO: Gitignore build output (build/, tPOS.pen)

# .gitignore
build/
tPOS.pen
*.pen.backup
```

### 4. Validation

```markdown
✅ DO: Validate after build
❌ DON'T: Skip validation

# Always validate:
jq empty tPOS.pen && echo "✅ Valid"
```

### 5. Configuration Consistency

```markdown
✅ DO: Keep pencil.config.json in sync
❌ DON'T: Hardcode paths in scripts

# Update config when structure changes
```

## Troubleshooting

### Build Script Errors

**Error: Component library not found**
```bash
# Check config
cat pencil.config.json

# Verify path exists
ls -la src/components/ui-kit.pen
```

**Error: Invalid JSON in source file**
```bash
# Validate source files
jq empty src/components/ui-kit.pen
jq empty src/pages/desktop-home.pen
```

**Error: Component ref not resolved**
```bash
# Check component exists in library
jq '[.children[0].children[] | select(.name == "Button/Primary")]' src/components/ui-kit.pen

# Check component path syntax
# Correct: "ui-kit#Button/Primary"
# Wrong: "Button/Primary" (missing library prefix)
```

### Output Validation

```bash
# Check file was created
ls -lh tPOS.pen

# Validate JSON structure
jq . tPOS.pen > /dev/null && echo "✅ Valid"

# Check version
jq '.version' tPOS.pen

# Count frames
jq '.children | length' tPOS.pen

# List frame names
jq '[.children[].name]' tPOS.pen
```

## Resources

- Back to [Pencil Design Skill](../SKILL.md)
- [File Format Reference](./FILE_FORMAT.md)
- [Atomic Design Reference](./ATOMIC_DESIGN.md)
- [Code Conversion Reference](./CODE_CONVERSION.md)
- [Workflow: /pencil-build](../../../.agent/workflows/pencil-build.md)
