Files
pos-system/microservices/.agent/skills/pencil-design/references/BUILD_SYSTEM.md
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

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)