Layers & Frames
OpenGPEX organizes content into Frames (artboards) containing Layers (visual elements). This page explains the data model, layer types, and how they map to the normalized state architecture.
Frames (Artboards)
A Frame is a top-level canvas container with its own:
- Dimensions (width × height in pixels)
- Background color (or transparent)
- Camera state (pan, zoom level)
- Layer stack (ordered collection of layers)
You can have multiple frames in a single project — useful for designing multiple views or sizes simultaneously.
Layer Types
| Type | Description | Use Case |
|---|---|---|
| Bitmap | Raster pixel data (photos, paintings) | Most common layer type |
| Text | Editable vector text with font styling | Headlines, labels |
| Group | Container holding child layers | Organizational hierarchy |
| Adjustment | Non-destructive filter (brightness, contrast) | Color correction |
| Mask | Alpha channel controlling parent visibility | Selective reveal/hide |
Layer Properties
Every layer has these core properties:
interface Layer {
id: string; // Unique identifier
name: string; // User-visible label
type: LayerType; // bitmap | text | group | adjustment | mask
visible: boolean; // Eye toggle
locked: boolean; // Prevent edits
opacity: number; // 0.0 – 1.0
blendMode: string; // normal, multiply, screen, overlay, etc.
// Geometry (local coordinate space)
x: number; // Position X
y: number; // Position Y
width: number; // Display width
height: number; // Display height
rotation: number; // Degrees
scaleX: number; // Horizontal scale
scaleY: number; // Vertical scale
// Assets
assetId?: string; // SHA-256 hash → CAS blob store
masks?: MaskDescriptor[]; // Attached clip masks
}
Z-Order and the order Array
Layers render bottom-to-top based on their position in the order array:
order: ["layer-bg", "layer-photo", "layer-text"]
▲ ▲
Bottom (drawn first) Top (drawn last, visible on top)
To move a layer up or down, you only rearrange the order array — the layer objects themselves are not touched.
Normalized State Mapping
Frames and layers both use the NormalizedState<T> pattern:
// State tree shape
state.frames = {
byId: {
"frame-1": {
id: "frame-1",
width: 1920,
height: 1080,
layers: {
byId: {
"layer-bg": { id: "layer-bg", type: "bitmap", ... },
"layer-text": { id: "layer-text", type: "text", ... },
},
order: ["layer-bg", "layer-text"],
},
},
},
order: ["frame-1"],
};
This structure provides O(1) lookups and minimal undo patches. See State Management for details.
Common Operations
| Operation | Action | Undo Behavior |
|---|---|---|
| Add layer | actions.addLayers() |
Remove on undo |
| Delete layer | actions.removeLayers() |
Restore on undo |
| Move layer (Z-order) | Rearrange order array |
Swap back on undo |
| Duplicate layer | actions.adv.duplicateLayer() |
Remove clone on undo |
| Merge down | actions.adv.mergeDown() |
Restore both layers |
| Group layers | actions.adv.groupLayers() |
Ungroup on undo |
Non-Destructive Editing
OpenGPEX preserves original pixel data at all times:
- Original asset stored in CAS (Content-Addressable Storage) by SHA-256 hash
- Layer metadata (position, scale, rotation, masks) stored as lightweight numbers
- Rendering combines asset + metadata on-the-fly — original is never modified
- Undo simply reverts metadata patches — no need to restore pixel data
Next Steps
- State Management — Deep-dive into NormalizedState
- Masks & Effects — Non-destructive masking system
- Rendering Pipeline — How layers become pixels
Last updated: 2026-06-14