456 lines
9.9 KiB
Markdown
456 lines
9.9 KiB
Markdown
# 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)
|