explain-interface
Answers how was this built about an interface. Give it a URL and name the thing you're curious about, and it reads the layers that produce the effect. Reads the whole frontend instead when you don't name a thing. From a screenshot it reconstructs rather than reads and says so.
Install
npx skills add https://github.com/jakubkrehel/skills --skill explain-interfaceReading the whole system
Use this where no specific effect was named and the question is how the interface is built in general. For one named thing, use find-the-effect.md [blocked].
Every recipe is a function that returns its data, so the result comes back whole. Run the stack first and tokens second, because a page that hands you its custom properties has already told you most of the answer.
Cross-origin sheets throw
sheet.cssRules throws on a cross-origin stylesheet. Every recipe that walks stylesheets wraps the access and returns the href it could not read. Fetch those sheets as in no-browser.md [blocked], or name them as unread. An explanation that silently skipped the main stylesheet describes a page nobody is looking at.
The stack first
"How was this site built" wants the frontend named before a type scale. Report each hit with the evidence that fired it.
Tokens
The walk recurses into @layer, @media and @supports, since Tailwind v4 writes its tokens as :root, :host inside @layer theme. It keeps a block only when the block applies and a rule only when its selector matches the root element. That reaches a theme layer under .dark or [data-theme="dark"].
Group the result by prefix, since the prefixes are the system's own layer names. declared keeps the authored value, often a var() chain, and computed is what that resolves to on the page right now. A two-tier structure, --blue-500 feeding --color-text-primary, is what better-colors calls primitives and semantic tokens.
The type scale
Leaf text nodes only, so a wrapper's inherited size is not counted as its own step.
Sorted by usage, so the body size usually comes first and the one-offs last. Derive the ratio between adjacent sizes. A consistent ratio is a scale, and scattered values are hard-coded sizes.
The spacing rhythm
Find the base unit that divides most values. Then measure the gap between groups against the gap within one. better-layout sets the yardstick at 2× or more for space to carry the grouping on its own.
Radii, shadows, borders
Report the count of distinct values and how often each is used. A few values reused everywhere is derived evidence of a shared scale. Whether anyone designed it is an inference.
Motion
transition: all shows up here as all. Custom curves arrive as cubic-bezier(...), and keywords such as ease are the browser's built-in curves.
Breakpoints
Compare against the framework defaults. Tailwind v3 ships 640px, 768px, 1024px, 1280px and 1536px as min-width. Tailwind v4 ships 40rem, 48rem, 64rem, 80rem and 96rem as width >= 40rem. A match is derived. Whether anyone chose to keep the defaults is an inference.
Fonts and theming
variable: true means one file covers a weight range. A class on <html> beside a prefers-color-scheme query means a toggle that can override the system setting.
Reading a second state
Everything above reads one state at one width. Before writing the explanation, at minimum:
- Resize to 375px and re-run the spacing and breakpoint recipes. The values that change are what is fluid.
- Toggle the theme and re-run the token recipe. Tokens whose
computedvalue changes are the themed layer, and the ones that do not are the primitives. - Tab to the first interactive control and read its
:focus-visiblestyles, which a page at rest never shows.