Skills jakubkrehel skills

state-machine

Use it when:
You're working on how one component looks and want each of its states, such as loading, empty, error or a locked feature, one keypress away.
It does:
Finds the states the component's code can reach and feeds each mock data from the page, through props or the app's own data seam.
You get:
A scratch page with the real, untouched component and a switcher where every state is a link, plus the state list and the switcher keys.
Unlike break:
That one, from the same repo, stacks worst-case scenarios on one page for a single look; this one is a workbench that stays up while you change the visuals.
Won't:
Add a branch to show a state the code can't reach, edit the component without asking, or change how a state looks unasked.
Runs:
Only when you call it.

Adds a scratch route to your app and leaves it there until you say you're done with it.

TL;DR

Part of Jakub Krehel's interface skills. It scopes the run to one component, then reads its code and data hooks for every branch: data states such as loading, empty, error, one item or a list long enough to scroll; account states such as plan tier and role; feature states such as flags, trials and limits. It writes the set down before building, grouped and named the way the product talks, and lists states the design shows but the code lacks instead of rendering them. The page sits in one folder inside the app, so it inherits the app's layout, fonts and providers; in Next it's a client page, so fixtures survive the server boundary. Mock data looks like the product, with real-shaped names, amounts and counts, and loading states stay pending until you switch. The switcher is styled deliberately outside your design system, sets a __state URL parameter, steps through states with the arrow keys and hides with H for screenshots. It checks every state once in a browser if one is at hand, and again after each visual change. On your word, it deletes the folder and searches for leftover route and fixture names.

Summarizes the skill at 60bf140.

npx skills add https://github.com/jakubkrehel/skills --skill state-machine
Weekly Downloads week to Nov 9, 2026
2,058
8 weeks

More weekly downloads than 80% of skills

Weekly values
Week toInstalls
Sep 210
Sep 280
Oct 50
Oct 121,038
Oct 191,226
Oct 261,402
Nov 21,991
Nov 92,058
Total Downloads on skills.sh
7,800

Fewer downloads than 60% of skills

Repo stars jakubkrehel/skills
11,765

More stars than 60% of repos

Age published Oct 6, 2026
4 weeks

Newer than 98% of skills

Category

Taste for interfaces that don't look generated: direction, motion and accessibility.

Everything for building software: planning, coding, debugging, design, frameworks, cloud, agents and skills.

Type

A multi-step process the agent follows: interview, debug, run a TDD loop, review.

Effect

Its own steps create or change files, git state or local tools.

Needs

Instructions only. Works in any agent that supports skills.

Publisher

Everyone else. Unverified vendor claims default to community.

Topics

SKILL.md

From jakubkrehel/skills at 60bf140. Checked daily, last changed Nov 6, 2026.

Frontmatter
name: state-machine
description: Renders every state of a component you choose on a throwaway page, with mock data and a switcher, so you can work on each state.
disable-model-invocation: true

State machine

This skill takes one component and renders it on a throwaway page in every state it can be in. Mock data feeds each state, a switcher flips between them and the page is deleted in one step when you are done.

It is a workbench, not a review. The page stays up while the user works on the visuals, one state on screen and every other a keypress away. Stacking hostile scenarios on one page for a single look is break, exploring alternative designs is variant and reviewing finished work is interface-review.

1. Scope one component

One component per run: the audit log table, the network panel, the billing card. "The settings page" spans several, so list them and ask which one.

Restate it in one sentence: what the component shows, where it renders in production and where its data comes from.

2. Find the states in the code

The states are the branches the component already has. Read it and its data hooks for every one:

Kind States
Data Loading, empty, error, one item, a typical set, a set long enough to scroll or paginate, some requests resolved and others pending, stale data refetching
Account Plan tier, role and permission checks, an owner versus a member
Feature Flags, trials, limits reached, a disabled or locked feature

A state the code cannot reach is not a state. Do not add a branch to render one. Where the design shows a state the code lacks, list it as missing and leave it out.

Write the set down before building, one line each, named the way the product talks about it: empty, enterprise, member-no-access. Group them under headings in the product's words, by what changes. Use Data and Account or narrower ones such as Connection or Access. The switcher shows these groups. Say which kinds you dropped and why in one line. Combine kinds only where the code branches on the combination, such as member-empty, never as a cross product.

3. Build the throwaway page

A scratch route inside the app holds the real component, imported from the project and untouched. The route inherits the app's layout, fonts, global styles and providers for free.

Where the framework splits server from client components, the page is client code, "use client" in Next. Otherwise fixture data can silently vanish crossing that boundary, and the page renders empty.

Render one instance in a container as wide as the component is in production. The container, the fixtures and the switcher are everything the page adds, with no fonts, styles or themes of its own. Keep the page, its fixtures and its switcher in one folder, such as /states/audit-log, so removal is one delete.

4. Feed each state at the data boundary

Supply the data where the component receives it, from the page, without editing the component. In order of preference:

  1. Props, where the component takes its data as props.
  2. The app's own data seam: a seeded query cache, a mock provider or the project's request mocks.

A fixture threaded through props five levels down tests a path production never takes. Where the only way in is editing the component, say so and ask before adding a seam.

Make the data look like the product. Real-shaped names, timestamps, amounts and the item counts users actually have. Three rows of "Test item" make every state look fine.

Loading and pending states hold still. Keep them pending until the switcher moves, rather than resolving after a timeout.

5. Add the switcher

A grouped list beside the component flips the __state search param, so every state is a link. Where there is no room beside the component, it moves above it as a select with the same groups. The double underscore keeps it clear of any param the app's layout reads. switcher.md holds the spec.

6. Confirm every state renders, then hand over

Load the page once in a browser already at hand and flip through every state. The component shows the mock data, not the real data and not a blank region. Mock data that never appears is the common failure here. Live sync, a cache that refetches over the seed or a server boundary dropping the fixture all cause it. Fix the plumbing before handing over.

With no browser at hand, say so and hand the URL over for the user to check.

Then hand over the URL, the state list and the switcher keys. Stop there. Changing how a state looks is the user's next request, not part of this one.

Re-check every state after each change

After a visual change, flip through every state again, since a fix for one state often breaks another.

Remove it in one step, on the user's word

Delete the page folder and any seam the user approved. Then search the codebase for the route and fixture names, and check that the diff touches nothing else of the setup.

Before you finish

Mistake Fix
The component edited to accept fixtures Feed data from the page through props or the app's data seam; ask before adding a seam
A rebuilt lookalike component on the page Import the real component from the project
The page restyles or re-themes the component The app's layout, fonts and tokens as they are
Fixtures passed as props deep in the tree Supply the data where the component receives it
A branch added to the component to show a state Leave out states the code cannot reach, and list missing ones
"Item 1", "Test user", three rows Product-shaped data in real quantities
Loading resolves after a timeout Hold it until the switcher moves
Handed over without loading each state Load every state; a blank or real-data state means broken plumbing
Switcher styled with the project's tokens Keep it visibly outside the design system
One long row of tabs, one per state A grouped list beside the component that scrolls on its own; a select above it where the list does not fit
Visuals changed unasked Hand over and wait
Page deleted in the same turn it was built Remove it only on the user's word
Route or fixture names left behind Search for both after removal