gpui

SKILL.md

GPUI Best Practices

Comprehensive guide for building desktop applications with GPUI, the UI framework powering Zed editor. Contains 40+ rules across 8 categories, prioritized by impact.

When to Apply

Reference these guidelines when:

  • Writing new GPUI views or components
  • Implementing state management with Entity
  • Handling events and keyboard shortcuts
  • Working with async tasks and background work
  • Building forms, lists, or dialogs
  • Styling components with Tailwind-like API
  • Testing GPUI applications

Rule Categories by Priority

Priority Category Impact Prefix
1 Core Concepts CRITICAL core-
2 Rendering CRITICAL render-
3 State Management HIGH state-
4 Event Handling HIGH event-
5 Async & Concurrency MEDIUM-HIGH async-
6 Styling MEDIUM style-
7 Components MEDIUM comp-
8 Anti-patterns CRITICAL anti-

Quick Reference

1. Core Concepts (CRITICAL)

  • core-ownership-model - Understand GPUI's single ownership model
  • core-entity-operations - Use read/update/observe/subscribe correctly
  • core-weak-entity - Use WeakEntity to break circular references
  • core-context-types - Know when to use App, Context, AsyncApp

2. Rendering (CRITICAL)

  • render-render-vs-renderonce - Choose Render for stateful, RenderOnce for components
  • render-element-composition - Build element trees with div() and method chaining
  • render-conditional - Use .when() and .when_some() for conditional styling
  • render-shared-string - Use SharedString to avoid string copying
  • render-builder-pattern - Design components with builder pattern

3. State Management (HIGH)

  • state-notify - Always call cx.notify() after state changes
  • state-observe - Use cx.observe() to react to Entity changes
  • state-subscribe - Use cx.subscribe() for typed events
  • state-global - Use Global trait for app-wide state
  • state-keyed-state - Use window.use_keyed_state() for persistent state

4. Event Handling (HIGH)

  • event-actions - Define and register actions for keyboard shortcuts
  • event-listener - Use cx.listener() for view-bound event handlers
  • event-focus - Manage focus with FocusHandle and key_context
  • event-propagation - Understand event bubbling and stop_propagation

5. Async & Concurrency (MEDIUM-HIGH)

  • async-task-lifecycle - Store or detach tasks to prevent cancellation
  • async-debounce - Implement debounce with timer + task replacement
  • async-background-spawn - Use background_spawn for CPU-intensive work
  • async-weak-entity - Use WeakEntity for safe cross-await access
  • async-error-handling - Use .log_err() and .detach_and_log_err()

6. Styling (MEDIUM)

  • style-flexbox - Use h_flex() and v_flex() for layouts
  • style-theme-colors - Always use cx.theme() for colors
  • style-spacing - Use DynamicSpacing for responsive spacing
  • style-elevation - Use elevation system for layered surfaces

7. Components (MEDIUM)

  • comp-stateless - Prefer RenderOnce with #[derive(IntoElement)]
  • comp-traits - Implement Disableable, Selectable, Sizable traits
  • comp-focus-ring - Add focus ring for accessibility
  • comp-dialog - Use WindowExt for dialog management
  • comp-variant - Use variant enums for component styles

8. Anti-patterns (CRITICAL)

  • anti-silent-error - Never silently discard errors with let _ =
  • anti-drop-task - Never drop Task without storing or detaching
  • anti-drop-subscription - Always detach or store subscriptions
  • anti-circular-reference - Avoid Entity cycles, use WeakEntity
  • anti-missing-notify - Never forget cx.notify() after state changes
  • anti-unwrap - Avoid unwrap(), use ? or explicit handling

Architecture Overview

┌─────────────────────────────────────────────────────────┐
│                    Application (App)                     │
│              (Single owner of all Entities)              │
└─────────────────────────────────────────────────────────┘
        ┌───────────────────┼───────────────────┐
        │                   │                   │
    ┌───────────┐       ┌───────────┐       ┌──────────┐
    │ Entity<A> │       │ Entity<B> │       │ Global<C>│
    └───────────┘       └───────────┘       └──────────┘
        │                   │                   │
        │ read/update       │ read/update       │ via App
        │ via Context<A>    │ via Context<B>    │
    ┌─────────────────────────────────────────────────┐
    │           UI Rendering (Render trait)           │
    │      Each frame: fn render(&mut self, ...)      │
    │      Returns: impl IntoElement (Element tree)   │
    └─────────────────────────────────────────────────┘
        ├─ observe() → changes trigger render
        ├─ subscribe() → events trigger reactions
        ├─ notify() → signal changes
        └─ emit() → send typed events

How to Use

Read individual rule files for detailed explanations and code examples:

rules/core-ownership-model.md
rules/render-render-vs-renderonce.md
rules/anti-silent-error.md

Each rule file contains:

  • Brief explanation of why it matters
  • Incorrect code example with explanation
  • Correct code example with explanation
  • Additional context and references
Weekly Installs
20
GitHub Stars
5
First Seen
Jan 21, 2026
Installed on
opencode19
codex19
github-copilot18
cursor18
gemini-cli17
amp16