Agent skill

Expressive Mvc

by gabeklein in gabeklein/expressive-mvc

Class-based reactive state management for React (Expressive MVC).

MITAuto-check passedFrontend & Design

Install Expressive Mvc

skills CLI
$ npx skills add gabeklein/expressive-mvc --skill expressive-mvc -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install gabeklein/expressive-mvc expressive-mvc --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/gabeklein/expressive-mvc.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills .claude/skills/expressive-mvc && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
expressive-mvc
GitHub stars
103
Token cost
~5.9k tokens
SKILL.md length
2,323 words
Files
28
Skills in repo
1
Repo updated
First seen
Licence
MIT

At a glance

Class-based reactive state management for React (Expressive MVC).

  • Works in 12 steps: Identify lifecycle and ownership… → Separate headless workflow state from… → Choose State, Component, or a plain… → …
  • Refactoring React state - converting useState/useEffect/useMemo hooks
  • SKILL.md covers Packages, Start With Ownership, Not APIs, Golden-Path Refactor Algorithm and Core API, plus 8 more sections
  • Calls npm and composer; reaches expressive.dev

What it does

Expressive Mvc is an agent skill from gabeklein/expressive-mvc. Class-based reactive state management for React (Expressive MVC). Use when writing or refactoring React state - converting useState/useEffect/useMemo hooks, fixing prop drilling, choosing state ownership (State vs Component, has-pool domain rows, region controllers), dependency snapshots, presence boundaries with get(true), providing context, async suspense, router - and when auditing a codebase for fit.

Its SKILL.md is about 5.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 31 other files (for example `design.md`, `dom/dom.md` and `examples/audit.md`).

It sits in Frontend & Design, covering State management and Refactoring. It works with React. The repository describes itself as: Define classes to organize and control state used by React apps. The licence is MIT.

When your agent uses it

  • Refactoring React state - converting useState/useEffect/useMemo hooks
  • Fixing prop drilling
  • Choosing state ownership (State vs Component
  • Has-pool domain rows

Example prompts

  • “/expressive-mvc”

Requirements

  • Node.js

Workflow steps

12 steps, taken from the first numbered list in SKILL.md.

  1. Identify lifecycle and ownership boundaries before translating any hooks.
  2. Separate headless workflow state from display-intrinsic state.
  3. Choose State, Component, or a plain function component for each owner.
  4. Give every repeated UI entry own class in a has pool; actions about item belong on item.
  5. Split unrelated clusters remaining on page State to owned region States composer = new Composer(). Bias one concern per class - barrels…
  6. Provide classes directly never an instance if only to provide it; the entrypoint Component's own fields provide implicitly - main only…
  7. Move source fields and behavioral methods first; do not mechanically translate setters.
  8. Keep shared, semantic derivations as getters; leave single-consumer display derivations in their consuming component.
  9. Let contextual children call .get() instead of receiving drilled props.
  10. At every .get() / .use(), destructure for exact nested dependency snapshot.
  11. May assign thru subscribed proxies; is only to retain the root object alongside sibling destructuring.
  12. A gated widget mounts unconditionally and gates itself, falling thru when unset; parent gate + .get(true) where the parent reads the field…

What it can do on your machine

Read from SKILL.md and the folder at commit 80f74b3. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npm
    • composer

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • expressive.dev

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Expressive Mvc loads about 5.9k tokens when it runs. Until then it costs about 106 tokens; SKILL.md has 2,323 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~106
When it runs · the whole SKILL.md, loaded when a task matches
~5.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from gabeklein/expressive-mvc at commit 80f74b3, republished under its MIT licence (© gabeklein). 2,323 words, ~5,862 tokens.

Download SKILL.mdSave it as .claude/skills/expressive-mvc/SKILL.md (or your agent's skills folder). This skill also uses 27 other files; get the full folder from GitHub.
name
expressive-mvc
description
Class-based reactive state management for React (Expressive MVC). Use when writing or refactoring React state - converting useState/useEffect/useMemo hooks, fixing prop drilling, choosing state ownership (State vs Component, has-pool domain rows, region controllers), dependency snapshots, presence boundaries with get(true), providing context, async suspense, router - and when auditing a codebase for fit.

Expressive MVC

Class-based reactive state for React. State classes define reactive properties, computed values, async data, and context - all as plain class fields using instruction helpers.

Packages

PackageStatusDescription
@expressive/mvcPublishedFramework-agnostic core. Primary import for State, Component, instructions.
@expressive/reactPublishedReact adapter. Supplies the host.
@expressive/domPreviewMVC-native client DOM renderer without a framework dependency.
@expressive/preactPrivateThin wrapper over React adapter via preact/hooks. Prerelease.
@expressive/routerPublishedHost-agnostic, class-based router built on MVC.
@expressive/inspectPublishedIn-process inspector: registry, ownership tree, path queries, journal.
Installing
bash
npm install @expressive/mvc @expressive/react    # + @expressive/router for routing

@expressive/mvc is a peer dependency - add it to package.json and import State, Component and every instruction from it, whatever the host. @expressive/react supplies the host: import it once from your entry module so it registers. Its re-exports of the core are deprecated and will be removed, as is the default export of State - adapter-augmented State.* types are invisible through the default alias, so import { State } by name.

React Native / Expo need no setup beyond three boundaries (react/react.md): add @expressive to jest-expo's transformIgnorePatterns; use Router, not BrowserRouter; Link/NavLinks render DOM, so navigate through Router.

For a client-only DOM app without React, install @expressive/mvc and @expressive/dom. @expressive/dom is a sidecar and re-exports nothing - State, Component and instructions come from @expressive/mvc, while render, Portal, style and macro come from @expressive/dom. Its FC model, renderer API, portals, code splitting, and transition constraints are in dom/dom.md.

Start With Ownership, Not APIs

The most common failure when adopting this library is translating hooks one-for-one before deciding who owns each behavior. Resolve ownership first; APIs come second.

For every stateful concern, pick exactly one owner:

  • Component - state intrinsic to one display subtree: controls, panels, editors, review/confirm surfaces. Usually defines render(). Fields, handlers, and rendering live on one class. The app/route entrypoint is one even when render() only composes: it owns construction (replica + region State fields), provides implicitly, and ships last-resort catch/fallback - main just mounts it.
  • State - headless model or workflow: network operations, domain rules, cross-view coordination. Views subscribe via State.get() / State.use().
  • Plain function component - simple presentation, or trivial local UI state. Not everything needs a class.

Concerns include the rows: UI state describing an entry in a collection - selection, status, progress - is its own State or Component spawned in a has pool; actions about item belong on item. Id-keyed fields (Record<Id, T>, parallel Maps) and (id, value) methods are a missing class; subsets are a second pool admitting the same members.

Counter-rules:

  • Do not create FooState plus FooView just because hooks were present. If the behavior and rendering are one unit, class Foo extends Component is the refactor.
  • Avoid Component where a provided State suffices - Components carry React instance surface (props, state, setState, forceUpdate) that makes .get() IntelliSense noisier.
  • Prefer an FC over Component when state is zero or reducible and no boundary is wanted - a class holding only get(...) fields plus render() is an FC snapshotting .get().
  • A render-less Component (children pass through while providing context and boundary placement) is only for cases where React tree placement is the feature: route controllers, progressive boundaries.
  • A provided State implicitly provides its child States - prefer theme = new Theme() on an existing owner over stacking <Component for> elements for every small controller.

Golden-Path Refactor Algorithm

Before refactoring existing React code, read react/refactor.md - it expands every step with before/after examples and ends with the review checklist. The short form:

  1. Identify lifecycle and ownership boundaries before translating any hooks.
  2. Separate headless workflow state from display-intrinsic state.
  3. Choose State, Component, or a plain function component for each owner.
  4. Give every repeated UI entry own class in a has pool; actions about item belong on item.
  5. Split unrelated clusters remaining on page State to owned region States composer = new Composer(). Bias one concern per class - barrels are deliberate (page orchestrator, pool owner, mounting shell); shed a second concern the moment it appears, growing a feature or refactoring one alike.
  6. Provide classes directly <Component for={AppState}> never an instance if only to provide it; the entrypoint Component's own fields provide implicitly - main only mounts <Inbox />.
  7. Move source fields and behavioral methods first; do not mechanically translate setters.
  8. Keep shared, semantic derivations as getters; leave single-consumer display derivations in their consuming component.
  9. Let contextual children call .get() instead of receiving drilled props.
  10. At every .get() / .use(), destructure for exact nested dependency snapshot.
  11. May assign thru subscribed proxies; is only to retain the root object alongside sibling destructuring.
  12. A gated widget mounts unconditionally and gates itself, falling thru when unset; parent gate + .get(true) where the parent reads the field for its own content.
  13. Split render() and long JSX at conditionals and non-interacting siblings into honestly-named local FCs - units you'd delete or move whole; one-op conditionals and formatted scalars stay inline. Consolidate scopes that share dependencies and hold no nested logic.
  14. Audit the result against the checklist in react/refactor.md.

For large apps, scope a one-shot conversion to route/page controllers and their domain pools; leave mature leaf widgets on hooks until parent domains stabilize.

Write output in the conventions of react/style.md. They are opinion, not semantics - but they exist to keep reactive dependencies auditable, and the golden path applies them by default.

Core API

tsx
import { State, Component, ref, def, get, has, map, pending, set } from '@expressive/mvc';
import '@expressive/react'; // once, in the entry module
State Class

Extend State to define reactive models. Use State.new() to construct a root instance - it constructs and activates, which plain new does not. Bare new is correct in one place: a class field on another State (theme = new Theme()), where the owner adopts and activates the child, and destroys it in turn.

tsx
class Counter extends State {
  count = 0;

  increment() {
    this.count++;
  }
}

const counter = Counter.new();
counter.count; // 0
counter.increment();
counter.count; // 1

Properties assigned in the class body are reactive - updates notify subscribers. Methods are auto-bound.

Instructions & Reactive Helpers

Field initializers that configure reactive behavior. Each has multiple overloads - fetch the reference when a task needs them.

HelperUse forReference
set()Defaults, placeholders (suspend until assigned), lazy/async factories (suspense), setter callbacks and validationfield/set.md
get()Context lookup between States - required or optional upstream, downstream collectionfield/get.md
ref()Mutable refs (.current), ref callbacks with cleanup, ref proxiesfield/ref.md
map()Reactive Map field - keyed entries or a keyed spawner, with owned State members and direct renderfield/map.md
has()Owned collections - an ordered list of values, or a pool of spawned members. Pools are for per-item UI state (selection, progress, row actions). Class first (has(Row)); factory when the seed isn't the initfield/has.md
def()Low-level custom property behaviorfield/def.md

For computed values, declare a normal class getter - getters on a State subclass are auto-promoted to memoized, dependency-tracked properties. See state/computed.md for tracking rules and when a derivation should not be a getter.

pending(work) is not a field helper but imports alongside them - it marks the updates work queues non-urgent and resolves once every reader has taken them. See Transitions.

Do not pass a bare promise to set(). Use set(() => promise) or set(async () => value) so work starts during activation/access instead of construction.

tsx
class UserProfile extends State {
  userId = set<string>();

  user = set(async () => {
    const res = await fetch(`/api/users/${this.userId}`);
    return res.json();
  });

  email = set('', (value) => {
    if (!value.includes('@')) throw false;
  });

  get displayName() {
    return `${this.user.firstName} ${this.user.lastName}`;
  }
}
React Hooks
tsx
// Local state - creates instance, owns lifecycle, subscribes to accessed fields
function MyComponent() {
  const { count, increment } = Counter.use();
  return <button onClick={increment}>{count}</button>;
}

// Context state - reads nearest provided instance, subscribes reactively
function Child() {
  const { count } = Counter.get();
  return <span>{count}</span>;
}

// An instance you already hold - place it; it renders and subscribes itself
function Parent({ counter }: { counter: Counter }) {
  return <section>{counter}</section>;
}

Static .use() and .get() are React hooks - call unconditionally at the top of a component or render(), never inside branch, event handlers, or loops. They build green when misused and crash at runtime. (Instance method get is not a hook.)

Use State.use() when the component should create and own the instance. Use State.get() when the instance comes from context. To render an instance you already hold, make it a Component and place as {instance} - subscription belongs to the placed instance, not the surrounding function. See react/react.md for overloads (optional lookup, required values, computed selector).

The Dependency Snapshot

Open every subscribing component by destructuring the exact reactive values it renders - nested ones included. Nested observable reads are proxied and tracked automatically, so nested destructuring subscribes to child fields; a child reached through a parent proxy needs no separate subscription.

tsx
function OrderSummary() {
  const {
    status,
    customer: {
      name,
      address: {
        city,
      } = {},
    },
  } = Order.get();

  return <p>{name} ({city ?? 'no address'}) - {status}</p>;
}

This is the norm, not a preference:

  1. The component's complete dependency surface is visible at the top - reviewable at a glance.
  2. Each trapped getter is traversed once, instead of re-walking order.customer.address.city in every expression.
  3. Reads create subscriptions. A deep read buried in a conditional branch subscribes only on renders where that branch runs - a conditional subscription. Hoisting reads into the snapshot makes the dependency surface deterministic.

Optional nested objects take in-place defaults (= {}) rather than a separate unwrap step. The same rule applies to this inside Component.render() and subcomponents - injected parents (inbox = get(Inbox)) are read thru that snapshot, never a second Inbox.get().

Show full SKILL.md (944 more words)Show less

Transparent Writes

Proxies pass assignments through to the instance, nested objects included - no unwrapping:

tsx
const form = LoginForm.get();                   // whole object needed - take it directly
<input value={form.username} onChange={(e) => (form.username = e.target.value)} />

const { transfer, confirmed } = ReviewStep.get();
<button onClick={() => (transfer.step = 'generate')} disabled={!confirmed} />

const { is: review, confirmed, hasBlocking } = ReviewStep.get();  // `is`: root beside siblings

is is only for keeping the root alongside sibling destructuring. Unwrapping every writable object through it is the most common misuse.

Presence Boundaries & get(true)

Default: a self-contained widget mounts unconditionally, reads its own context, and falls thru when its reason to render is unset - a parent read existing only to gate belongs in the widget. The secondary shape, when the parent reads the field for its own content: parent gates, child asserts with get(true):

tsx
function SettingsContent() {
  const { draft } = SettingsState.get();

  return (
    <div className="settings-layout">
      <LocationList />
      {draft && <SettingsEditor />}
    </div>
  );
}

function SettingsEditor() {
  const {
    saveSettings,
    saving,
    draft: {
      bankAccount,
      categoryAccounts,
    },
  } = SettingsState.get(true); // Required<T> - throws if an accessed value is undefined

  return <section className="settings-editor">...</section>;
}

This gives the child a strong contract - no fallback values threaded through its body. Declare gateable fields optional (draft?: SettingsLocation), not | null: the runtime check rejects only undefined, and Required<T> does not strip null from a union (see react/react.md). Both shapes in full: react/refactor.md step 12.

Providing Context

Pass the class: <Component for={TransferState}>. Pass an instance only when something else owns it (<Component for={counter}> after Counter.use()). One item per element - several belong to a parent State owning them as fields, which makes them siblings; nesting <Component for> is a smell (the outer cannot get the inner). is, attributes, boundaries: state/context.md.

Component Class

A Component is a State that renders itself. It provides context automatically and supports suspense/error boundaries.

tsx
class CounterView extends Component {
  count = 0;

  increment() {
    this.count++;
  }

  render() {
    const { count, increment } = this;
    return <button onClick={increment}>{count}</button>;
  }
}

<CounterView />;

const counter = CounterView.new();
<>{counter}</>;

An activated instance renders directly, arrays included; its owner keeps lifecycle, so unmount detaches without destroying.

PascalCase methods become reactive subcomponents - extension points a subclass would replace or wrap, not general decomposition. Otherwise write a freestanding FC calling MyComponent.get(). Details: react/component.md.

Rules & Counter-Rules

Every broad rule here has a locality constraint. Apply both halves. When auditing a result, weigh findings by the severity labels defined in react/refactor.md - invariant, default, heuristic, style - and never fail a heuristic on its numerical signal alone.

RuleCounter-rule
Reactive fields are assigned directlyKeep a method when the write validates, normalizes, coordinates fields, or triggers behavior. Delete methods whose body is only this.x = value.
Derived values become gettersOnly when shared by multiple consumers, semantic to the domain, expensive, or a deliberate part of the state's API/introspection surface. Single-consumer display derivations live in the consuming component - but judge meaning, not reference counts.
Contextual components read via .get()Pure presentation components may still take plain props. Context replaces drilled state, not every value.
PascalCase subcomponents compose rendersOnly for genuine extension points a subclass would replace or wrap. Implementation scopes are freestanding FCs using .get().
Extract long conditional JSX (~10+ lines or ~5+ levels)Keep branches together when they share dependencies, read locally, and contain no nested logic.
is retains the raw instanceOnly alongside sibling destructuring from the same snapshot. Writes through proxies are transparent; nested objects need no unwrapping.
State about a collection entry lives on the entry's classPayload keys that never drive UI stay as one info subobject on the member - a reactive field without a reader is pure cost.

File Reference

Fetch these for detailed documentation when the task requires deeper knowledge. Read react/refactor.md in full before any hook-migration or refactor task.

Design intent
  • design.md - why the library is shaped this way: classes hold models not views, the "MVC" mapping, the two-verb get/set surface, render composition as a designated seam, typed lifecycle hooks, transparent writes. Read before characterizing a design choice as accidental. For positioning against alternatives (Zustand, Jotai, MobX, Redux Toolkit, plain Context), see expressive.dev/llm/comparisons.md.
Golden path
  • react/refactor.md - the refactor algorithm expanded: ownership triage, mechanical-setter and prop-drilling anti-patterns, single-consumer getters, dependency snapshots and conditional subscriptions, presence boundaries, restrained is, subcomponent overuse, extract-then-consolidate, review checklist
  • react/style.md - style profile: snapshot formatting, affirmative conditions, render fallthrough vs operational guards
State (core)
  • state/state.md - State class, instantiation, properties, methods, events, context
  • state/get.md - Instance .get() method: read values, run effects, context lookup
  • state/set.md - Instance .set() method: write values, listen to updates, events, destroy
  • state/computed.md - Reactive class getters: tracking, caching, inheritance, suspense, when a derivation should stay local
  • state/lifecycle.md - Construction, activation, operation, destruction phases; hot patching and the hot seam
  • state/context.md - Context system, global root, home context, ownership rules
  • state/types.md - TypeScript type aliases and utility types

Instructions: field/*.md, linked from the helper table.

React
  • react/react.md - use(), State.use(), State.get() (optional lookup, required values get(true), computed selector), providing state, transparent writes, ForceRefresh, Vite hot reload
  • react/component.md - Component class, props, children, render composition, subcomponent extension points, error boundaries
  • react/patterns.md - Recipes: forms, async, domain-row and form-chip pools, region controllers, router bridge, host-agnostic model + view adapter, presence boundary, contextual children, debounce, effects
JSX
  • dom/dom.md - client DOM render/unmount, stateless FC scopes, MVC snapshots, native events, portals, lazy boundaries, transitions, Vite hot reload, exclusions
Router
  • router/router.md - route declarations, lexical matching, guards, Suspense, navigation state, and UI
  • router/production.md - choose Router vs BrowserRouter, page-data ownership, navigation settlement, testing, host boundaries, and unsupported browser behavior
Inspect
  • inspect.md - @expressive/inspect: install entry, instances in process vs addresses across a boundary, ownership, stored-value reads with absent, labels under minification, frame journal with cause, act, orphans and health(), bridge and Vite relay
Examples

Runnable examples - optional; this skill is complete offline. https://expressive.dev/examples/<group>/<name> serves a working program's every source file as plain HTML (no JS needed). Fetch one for a full reference implementation rather than a snippet:

GroupPages
featuredforms, kanban, spreadsheet, stopwatch, tictactoe
essentialscounter, computed, fetch, async
componentprops, subcomponents, lifecycle, injection, headless, suspense, boundary, custom
compositionnested, context, concerns, extension, globals
instructionsset, set-factory, set-computed, get, get-downstream, ref, ref-multiple, map, map-insert, has, has-list, def
routeroverview, browser, params, query, guards, transitions, nav, wizard

Auditing & Evaluation

Audit a conversion as a separate pass over the diff - self-audits while authoring under-report architecture gaps.

Fit and migration candidates: examples/audit.md; approved migrations follow react/refactor.md. Positioning: website-only why, comparisons, and dom vs React.

© gabeklein, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 27 other files in skills of gabeklein/expressive-mvc.

  • SKILL.md
  • design.md
  • dom/dom.md
  • examples/audit.md
  • examples/basic.md
  • field/def.md
  • field/get.md
  • field/has.md
  • field/map.md
  • field/ref.md
  • field/set.md
  • inspect.md
  • react/component.md
  • react/patterns.md
  • react/react.md
  • react/refactor.md
  • react/style.md
  • … and 11 more

Open the folder on GitHubat commit 80f74b3

Compare with similar skills

Expressive Mvc next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Expressive Mvc compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Expressive Mvc this skillgabeklein/expressive-mvc103—~5.9kAutomated safety check: PassMIT
Dify Component Writing Guidelanggenius/dify158k—~626Automated safety check: PassCustom licence
React Idiomsirahardianto/awesome-agv157—~3.8kAutomated safety check: PassMIT
Frontend Developmentavibebuilder/claude-prime120—~1.3kAutomated safety check: PassMIT
Vercel React Best Practicessanity-io/sanity6.4k129 repos~1.6kAutomated safety check: PassMIT
Frontend Module Standardssiteboon/claudecodeui14k—~2.6kAutomated safety check: PassAGPL-3.0

Similar skills

  • Use when implementing or refactoring React/TypeScript components and the task requires decisions about component ownership, feature boundaries, state, data…

    158k GitHub stars~626 tokensUpdated today
    Frontend & DesignAuto-check passed
  • React Idioms

    irahardianto/awesome-agv

    React 19+ patterns: custom hooks, Suspense boundaries, state management, component composition, and web performance.

    157 GitHub stars~3.8k tokensUpdated 4 days ago
    Frontend & DesignAuto-check passed
  • Frontend Development

    avibebuilder/claude-prime

    A skill your agent uses for ANY work involving React, Next.js, TypeScript, or Tailwind in the browser layer.

    120 GitHub stars~1.3k tokensUpdated 4 mo ago
    Frontend & DesignAuto-check passed
  • Official

    React and Next.js performance optimization guidelines from Vercel Engineering.

    6.4k GitHub starsUsed in 129 repos~1.6k tokens
    Frontend & DesignAuto-check passed
  • Frontend Module Standards

    siteboon/claudecodeui

    Enforces one repository's React and TypeScript module layout for code under src/: source-root imports, feature barrels, deliberate exports and no deep imports.

    14k GitHub stars~2.6k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Nuqs

    trycompai/crm

    nuqs (type-safe URL query state) best practices for Next.js and other React frameworks.

    11k GitHub starsUsed in 1 repo~1.7k tokens
    DevelopmentAuto-check passed

Works with

Questions about Expressive Mvc

What does Expressive Mvc do?

Class-based reactive state management for React (Expressive MVC). Expressive Mvc is an agent skill from gabeklein/expressive-mvc. Class-based reactive state management for React (Expressive MVC).

When should I use Expressive Mvc?

Expressive Mvc fits situations like: refactoring React state - converting useState/useEffect/useMemo hooks; fixing prop drilling; choosing state ownership (State vs Component; has-pool domain rows.

How do I install Expressive Mvc in Claude Code?

Run `npx skills add gabeklein/expressive-mvc --skill expressive-mvc -a claude-code`. Or copy the skill folder (skills in gabeklein/expressive-mvc) into .claude/skills/expressive-mvc in your project. Claude Code loads it when a task matches its description.

How do I install Expressive Mvc in Codex?

Run `npx skills add gabeklein/expressive-mvc --skill expressive-mvc -a codex`. Or copy the skill folder (skills in gabeklein/expressive-mvc) into .agents/skills/expressive-mvc in your project. Codex loads it when a task matches its description.

Can I use Expressive Mvc in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add gabeklein/expressive-mvc --skill expressive-mvc -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/expressive-mvc, .gemini/skills/expressive-mvc, .github/skills/expressive-mvc and .opencode/skills/expressive-mvc in your project.

What does Expressive Mvc need to run?

Going by SKILL.md and its folder, Expressive Mvc needs the command-line tools its instructions call (npm and composer). Our summary lists: Node.js.

Does Expressive Mvc access the network?

SKILL.md names 1 domain. In commands or code: expressive.dev; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Expressive Mvc safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Expressive Mvc use?

Expressive Mvc is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Expressive Mvc use?

About 5.9k tokens (SKILL.md is roughly 23k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Expressive Mvc?

Skills that share tags, products or a category with Expressive Mvc: Dify Component Writing Guide (langgenius/dify, 158k stars), React Idioms (irahardianto/awesome-agv, 157 stars), Frontend Development (avibebuilder/claude-prime, 120 stars) and Vercel React Best Practices (sanity-io/sanity, 6.4k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Expressive Mvc?

gabeklein (a GitHub user) maintains it in gabeklein/expressive-mvc, which has 103 GitHub stars. The repository was last updated on October 9, 2026.

Source: gabeklein/expressive-mvc on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.