| name | frontend-styling |
| description | Use when changing Tailwind utilities, theme tokens, responsive layout, class composition, or visual treatment. |
Generated from ai/registry.json. Do not edit manually.
Canonical skill: ../../../ai/skills/frontend-styling.md.
Referenced context:
../../../ai/rules/frontend-rules.md
../../../ai/rules/frontend-styling-rules.md
../../../ai/rules/frontend-quality-rules.md
This file is compiled from canonical AI knowledge files. Edit canonical files under ai, then run npm run ai:sync.
Compiled AI Skill: frontend-styling
Canonical Skill: ai/skills/frontend-styling.md
Frontend Styling
Use for Tailwind utilities, theme tokens, responsive layout, and visual treatment.
Read First
ai/rules/frontend-rules.md
ai/rules/frontend-styling-rules.md
ai/rules/frontend-quality-rules.md
Workflow
- Follow nearby shadcn-compatible UI patterns and semantic tokens in the single CSS entrypoint.
- Use static class strings when possible, the existing
cn helper for shared primitives/class merging, and established classnames usage in feature code when merge semantics are unnecessary.
- Check focus, reduced motion, themes, mobile layout, and visualization sizing.
- Run
npm run theme-colors:check, web build, and lint.
Referenced Context
Reference: ai/rules/frontend-rules.md
Frontend Rules
Boundaries
- Keep solving, notation semantics, puzzle validity, and replay verification in Rust. React renders and coordinates typed product workflows.
- Keep HTTP mechanics and normalization in
apps/web/src/api; UI consumes domain hooks/adapters.
- Typed scan-session contracts MAY contain reviewed stickers, confidence, and manual overrides. Notation solve UI MUST NOT expose facelet, Kociemba, or raw cube-state inputs.
- Keep API load, form, page workflow, solve result, scanner review, and visualization playback state separately owned unless a focused page owner coordinates them.
- Use the active
@rubiks-cube-solver/rubiks-cube package as a visualization adapter, never as canonical solver state.
Web Runtime And Locales
- Preserve static rendering for indexable routes,
hydrateRoot for generated markup, and SPA navigation after hydration.
- Keep
en-US canonical without a prefix. Publish/index any of the nine supported locales only when its visible and SEO content is fully translated with placeholder parity.
- Treat route slugs as stable identifiers. They need not be English and MUST NOT vary by locale; slug changes require redirects and canonical planning.
- Keep route/page code in its bounded context and shared code behind a demonstrated cross-context consumer.
Existing Patterns
- Prefer local state first, React Query for server state, and existing scoped Zustand stores only for genuinely shared client state.
- Use existing Radix-backed primitives for complex interaction semantics. Use the shared
cn helper in shadcn-style primitives and established classnames as cls in feature code when Tailwind conflict resolution is unnecessary.
- React Hook Form and Zod MAY be used when nearby code or form/schema complexity warrants them; they are not mandatory setup.
- New dependencies require the concrete checks in
frontend-quality-rules.md.
React Compiler
apps/web uses React 19 with React Compiler enabled through the Vite React compiler preset. Write ordinary components and hooks and let the compiler provide memoization.
- Do not add
useMemo, useCallback, React.memo, or other manual render memoization. Do not make referential identity a correctness requirement for effects, subscriptions, or child props.
- Do not use
forwardRef. React 19 components accept ref as a prop; type DOM-forwarding components with ComponentPropsWithRef and pass that prop to the owning element. A deliberate non-DOM imperative handle MAY use that prop with useImperativeHandle.
- Use
useEffectEvent when a callback registered by an effect must read the latest props or state without re-subscribing. Keep effect dependencies focused on the values that define the subscription lifecycle.
- Keep derived values and event callbacks as ordinary render-time code. Preserve no legacy memoization solely because it existed before the compiler.
- Do not read from or write to mutable refs during render, except for one-time initialization that React explicitly permits. Put imperative ref synchronization in effects or event handlers.
- Compiler skips unsafe functions rather than changing behavior. Fix Rules of React violations instead of adding blanket opt-outs; use
"use no memo" only as a short-lived, documented containment for a verified compiler issue.
Verification
- Run web build, lint, and targeted tests for changed behavior. Web lint runs Biome plus the official React Hooks/Compiler diagnostics and rejects manual memoization imports.
- Treat
npm run build as the compiler integration check because it exercises both the client bundle and the SSG build.
- Run SSG/SEO and E2E checks when routing, locales, metadata, hydration, scanner, timer, or solve flows change.
Reference: ai/rules/frontend-styling-rules.md
Frontend Styling Rules
- Use Tailwind CSS v4 through
@tailwindcss/vite; apps/web/src/index.css is the only CSS entry and owns resets, semantic variables, theme mappings, and minimal global animation definitions.
- Use semantic theme-backed classes. Raw hex values belong only in semantic variable definitions in
index.css.
- Preserve the established shadcn-compatible visual language, including semantic tokens, subtle borders, rounded corners, and restrained shadows. Design changes still require a concrete product reason.
- Use plain class strings when static. Shared shadcn-style primitives and components that merge caller classes MUST use the existing
cn helper; established feature code MAY continue to use classnames as cls when Tailwind conflict resolution is not needed.
- Preserve the established dark/gray visual tone, system theme behavior, mobile usability, visible focus, reduced motion, and the 350px cube cap.
- New CSS files, CSS-in-JS, Sass, hardcoded arbitrary colors, and broad selectors are prohibited.
- Run
npm run theme-colors:check, web build, and lint after relevant changes; inspect mobile and theme variants when affected.
Reference: ai/rules/frontend-quality-rules.md
Frontend Quality Rules
Focused requirements for accessibility, performance, security, resilience, and dependencies in apps/web.
Accessibility
- Interactive controls MUST have an accessible name, keyboard operation, visible focus, and correct native element or shared primitive semantics.
- Dialogs and sheets MUST preserve focus trapping, Escape handling, focus return, and labelled title/description behavior through existing primitives.
- When the timer page becomes interactive or a timer-page action completes, focus MUST return to the document body so its global keyboard controls remain available. This includes route navigation, event selection, and settings-dialog closure; controls remain focusable while users actively operate them.
- Dynamic errors and completion states SHOULD use an appropriate live/status region without repeatedly announcing scanner frame updates.
- Motion MUST respect reduced-motion preferences; color MUST NOT be the only signal for scan, validation, timer, or solver status.
Performance
- Indexable routes MUST retain SSG output and hydration; do not replace server-rendered content with client-only placeholders.
- Heavy visualization, algorithm, and page code SHOULD remain route- or feature-split. Avoid importing broad package barrels when a supported subpath exists.
- Supported Solver and Notation puzzle stages MUST automatically request their renderer. Solver visualizations MUST load no later than three seconds after mount; Notation visualizations MUST load automatically after their stage approaches the viewport. Clicking a preparing state MAY accelerate loading or retry an error, but MUST NEVER be required to see a visualization. Performance work MUST NOT defer any supported visualization behind an explicit click; tests MUST prove automatic loading for Solver and every supported Notation puzzle.
- Camera analysis MUST cancel stale work and avoid overlapping unbounded requests. Versioned assets remain immutable; mutable HTML and metadata MUST NOT receive immutable caching.
- Performance changes MUST use a concrete signal such as bundle output, request count, render behavior, or measured interaction, not speculative memoization.
Security And Resilience
- Camera permission MUST follow a clear disclosure of purpose and processing. Once permission succeeds, scanner analysis starts automatically by default; users retain pause/exit and manual-review controls.
- Images and reviewed scan data MUST stay within typed scan contracts and configured request limits. Do not persist or transmit camera data beyond the disclosed solve workflow.
- Browser code MUST not weaken CSP, permissions policy, origin restrictions, request size limits, runtime response validation, or typed error handling.
- Async work MUST handle cancellation and stale responses. User-visible flows MUST expose recoverable API/camera failures and avoid silently fabricating successful data.
- Analytics, RUM, and error-tracking services are out of scope unless a separate product/privacy decision explicitly introduces them.
Dependencies
- A new runtime dependency MUST solve a named current gap that existing React, browser APIs, shared primitives, or installed packages cannot reasonably solve.
- The change MUST identify bundle/runtime impact, maintenance owner, licensing/security fit, SSR/hydration compatibility when relevant, and focused tests.
- Do not add a package solely for a small helper, styling convention, or abstraction without a current reused consumer.