home / skills / velcrafting / codex-skills / state-modeling

state-modeling skill

/skills/frontend/state-modeling

This skill defines explicit frontend state models for complex flows, mapping states, events, and derived selectors to improve testability and reliability.

npx playbooks add skill velcrafting/codex-skills --skill state-modeling

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.6 KB
---
name: state-modeling
description: Define client state shape and transitions for non-trivial UI flows (multi-step, branching, async, derived state).
metadata:
  short-description: Explicit UI state + transitions
  layer: frontend
  mode: write
  idempotent: false
---

# Skill: frontend/state-modeling

## Purpose
Make non-trivial UI state explicit and testable by defining:
- state shape
- transitions
- derived selectors
- async and error pathways

Use when UI behavior is more than “render props and call an API”.

---

## Inputs
- Target UI flow (screen/component) and its states
- Events/actions that cause transitions
- Any async edges (fetch, debounce, retry, polling)
- Existing state system:
  - local state / reducer
  - context
  - Zustand/Redux/XState/etc (prefer repo profile)
- Repo profile (preferred): `<repo>/REPO_PROFILE.json`

---

## Outputs
- State model implementation aligned with repo patterns:
  - reducer/state machine/store module as appropriate
- Transition definitions (explicit mapping from event → next state)
- Derived selectors/utilities where needed
- Minimal tests if repo uses state unit tests (recommended when non-trivial)

---

## Non-goals
- Changing backend logic or API contracts
- Introducing new state libraries without explicit request
- Large refactors unrelated to the target flow

---

## Workflow
1) Identify the smallest state model that makes behavior explicit.
2) Enumerate states and events:
   - idle, loading, success, error, empty (if data-driven)
   - plus domain-specific UI states (editing, confirming, submitting, etc.)
3) Implement transitions:
   - event-driven (actions)
   - include error and retry transitions
   - include cancellation/reset paths if applicable
4) Keep rendering components dumb:
   - state model owns transitions
   - UI consumes state + dispatches events
5) Validate with repo commands and minimal tests where appropriate.

---

## Checks
- State transitions cover all expected UI paths
- Async flows have deterministic handling (retry/cancel/timeout if relevant)
- No unreachable or dead-end states introduced
- Typecheck passes (if configured)

---

## Failure modes
- Flow is ambiguous → invoke `$ask-questions-if-underspecified` or `meta/intake-interview`.
- State complexity growing uncontrolled → recommend splitting into sub-flow modules.
- Async edge cases missed → recommend `system/state-machine-mapper` for very complex flows.

---

## Telemetry
Log:
- skill: `frontend/state-modeling`
- state_system_used: `useReducer | zustand | redux | xstate | context | other`
- files_touched
- outcome: `success | partial | blocked`

Overview

This skill defines explicit client state shapes and deterministic transitions for non-trivial UI flows, including multi-step, branching, async, and derived-state scenarios. It produces a minimal, testable state model aligned with the repository's existing patterns so UI components stay dumb and predictable. The goal is to make behavior explicit, cover async/error edges, and enable reliable unit tests and integration checks.

How this skill works

I inspect the target UI flow, enumerate all states and events, and choose the smallest state model that expresses required behavior. I implement transitions (reducer, state machine, or store module) consistent with the repo profile, add derived selectors where useful, and include minimal tests for determinism. Async paths get explicit handling for loading, success, error, retry, cancel, and timeout as appropriate.

When to use it

  • Multi-step forms or wizards with branching paths
  • Components with complex async behavior (fetch, debounce, retry, polling)
  • Flows where UI state is derived from multiple sources or inputs
  • When current UI logic is spread across components and hard to test
  • When you need deterministic transitions and unit-testable behavior

Best practices

  • Model the smallest state machine that makes behavior explicit; avoid over-engineering
  • Keep rendering components dumb: state model owns transitions and business rules
  • Cover async edges: explicit loading, error, retry, cancellation, and timeouts
  • Provide derived selectors to centralize computed state and reduce duplication
  • Add minimal unit tests for transitions and key async paths to prevent regressions

Example use cases

  • A checkout flow with address validation, payment step, and optional promo flows
  • A multi-step onboarding wizard that conditionally shows steps based on user input
  • A list view with debounced search, optimistic updates, and retryable fetches
  • An edit/confirm workflow where cancel, save, and autosave transitions must be deterministic
  • Branching approval flows where different roles see different next steps

FAQ

Will you introduce a new state library?

No. I use the repo's existing state system (useReducer, context, Zustand, Redux, XState, etc.) unless you explicitly request a different library.

How do you handle async errors and retries?

Async edges are modeled explicitly with dedicated states for loading, success, error, retry, and cancel. Retry and timeout transitions are implemented where relevant and covered by tests.