Claude-skill-registry flui-architecture-expert
Expert on FLUI's three-tree architecture (View-Element-Render), widget composition, and Flutter-inspired patterns. Use when discussing views, elements, render objects, widget trees, or UI architecture.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/flui-architecture-expert" ~/.claude/skills/majiayu000-claude-skill-registry-flui-architecture-expert && rm -rf "$T"
manifest:
skills/data/flui-architecture-expert/SKILL.mdsource content
FLUI Architecture Expert
Deep expertise in FLUI's Flutter-inspired three-tree architecture.
When to Use
Activate this skill when the user:
- Asks about View, Element, or RenderObject
- Discusses widget composition or tree structure
- Wants to understand build/layout/paint phases
- Needs to create custom render objects
- Has questions about the BuildContext
Three-Tree Architecture
View Tree (Immutable)
Purpose: Declarative UI description Lifecycle: Created fresh each build Key trait: View with build() -> impl IntoElement
Rules:
- Views must be
but NOT necessarily Clone'static - Use cheap-to-clone types (String, Arc<T>)
- Never mutate state directly - use signals
Element Tree (Mutable)
Purpose: Manages widget lifecycle and state Storage: Slab<Node<Element>> with ElementId keys Key struct: Element with view_object: Box<dyn ViewObject>
Critical Pattern - ElementId Offset:
// Slab uses 0-based, ElementId uses 1-based (NonZeroUsize) let id = slab.insert(node); ElementId::new(id + 1) // +1 for insertion slab.get(element_id.get() - 1) // -1 for access
Render Tree (Layout/Paint)
Purpose: Layout calculation and painting Arity system: Leaf, Single, Optional, Variable Key trait: RenderBox<Arity>
Arity Types:
pub struct Leaf; // 0 children (Text, Image) pub struct Single; // 1 child (Container, Padding) pub struct Optional; // 0-1 children (Conditional) pub struct Variable; // N children (Row, Column)
Pipeline Phases
Build Phase
- Traverses dirty elements
- Calls
to generate new view treeview.build(ctx) - Reconciles with existing element tree
Layout Phase
- Top-down constraint passing
- Bottom-up size determination
- Uses
for flexible sizingBoxConstraints
Paint Phase
- Generates display list
- Layer composition
- GPU command generation via wgpu
Widget Patterns
Stateless Widget
pub struct MyWidget { pub text: String, } impl View for MyWidget { fn build(&self, ctx: &mut BuildContext) -> impl IntoElement { Text::new(&self.text) } }
Stateful Widget (with hooks)
impl View for Counter { fn build(&self, ctx: &mut BuildContext) -> impl IntoElement { let count = use_signal(ctx, 0); Button::new(format!("Count: {}", count.get())) .on_press(move || count.set(count.get() + 1)) } }
Custom RenderObject
impl RenderBox<Single> for CustomRender { fn perform_layout(&mut self, constraints: BoxConstraints) -> Size { let child_size = self.child().layout(constraints); Size::new(child_size.width + 20.0, child_size.height + 20.0) } fn paint(&self, context: &mut PaintContext) { context.canvas.draw_rect(self.local_rect(), &self.paint); self.child().paint(context); } }
Common Issues
Issue: Hook order changes
// BAD: Conditional hook if condition { let signal = use_signal(ctx, 0); // Will panic! } // GOOD: Always call hooks in same order let signal = use_signal(ctx, 0); if condition { // use signal }
Issue: Expensive rebuilds
// BAD: Large subtree rebuilt on every change Column::new(vec![ expensive_widget_tree(), // Rebuilt every time ]) // GOOD: Use memoization or separate signals let memoized = use_memo(ctx, || expensive_widget_tree());
Architecture Verification Checklist
- Views are immutable
- State managed through signals
- ElementId uses +1/-1 offset correctly
- RenderObject arity matches child count
- No mutable references across tree boundaries
- BuildContext only accessed during build phase