Fine Design logo

Fine Design

Community
anon5376
fine-design

Use when building or restyling React UI in a project that uses Fine (fine-design, @fine/ components, theme-ledger, theme-folio, theme-poster), or when asked to install or use Fine components. Fine is a shadcn registry on Base UI, Tailwind v4 and Motion. Behavior is the same everywhere; appearance is a preset (Ledger, Folio, Poster).

Overview

Publisheranon5376
Repositoryfine-design
Skill namefine-design
Stars
6
Forks
0
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by anon5376 on GitHub. Read the source before you install it.

Installation

Install the Fine Design AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/anon5376/fine-design/tree/main/plugin/skills/fine-design
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/anon5376/fine-design.git /tmp/fine-design
mkdir -p .claude/skills
cp -r /tmp/fine-design/plugin/skills/fine-design .claude/skills/fine-design
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Fine Design in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Fine Design on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Fine Design is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Fine

React design system as a shadcn registry. 52 components, 7 blocks, 4 lib files, fine-base and 4 theme items. Site: https://fine-design.qeqx.chatgpt.site

Behavior is universal: Base UI roles, keyboard and focus, validation, reduced motion, the motion tiers, the accessibility contracts, and styling through tokens only. Appearance is a preset: Ledger, Folio or Poster, each a set of token values.

Direction first

Before building a new site, page or screen, settle the direction. Read the project's design doc if it has one (DESIGN.md or similar). Otherwise decide these from the brief and write them into a short DESIGN.md first: audience, content, typography, palette, composition, imagery, interaction character. Then pick the closest preset, or derive a new one (see Making a preset), and build with Fine components.

Use Ledger when the user asks for it, or when the job is a dense data or operations tool. A small edit inside an existing screen follows that screen's direction; skip this step for it.

PresetDirectionTake it for
LedgerAchromatic, dense, flat at rest, ink chrome with one cobalt accentDashboards, admin and finance tools
FolioEditorial, set for reading: warm paper, serif titles, one quiet aubergine accentDocs, publications, content-led pages
PosterLoud, large type, strong contrast: a flat hot magenta for the main action and the accent, hard shadowsLaunches, campaigns, marketing pages

The table states each preset's intent. The values are in the theme item (npx shadcn@latest view @fine/theme-<name>) and in scripts/presets/<name>.mjs in the Fine repo.

Setup

Needs React 19, Tailwind v4, and a shadcn components.json with the default aliases (@/components, @/components/ui, @/lib). Run npx shadcn@latest init first if the project has none.

Install a theme once, then components. A component never re-skins a project.

  1. Register the namespace in components.json:
    json
    "registries": { "@fine": "https://fine-design.qeqx.chatgpt.site/r/{name}.json" }
  2. Install one theme: npx shadcn@latest add @fine/theme-ledger (or theme-folio, theme-poster). It writes values only (colors, fonts, weights, radii, type scale, control sizes, padding, border width, shadows) to :root, .light, .dark and the OS dark query. A second theme replaces the first; put overrides in a later rule. fine-theme is an alias of theme-ledger. Tailwind's palette stays.
  3. Add components: npx shadcn@latest add @fine/button @fine/dialog. Each depends on fine-base (the @theme inline mappings, the figures, figure-fit, focus-ring and border-line utilities, keyframes, motion scalars, and Ledger defaults in @layer base) plus other items and npm packages. Your :root and the installed theme beat those defaults, so adding a component later does not change the look. With no theme installed, components render in Ledger.
  4. After shadcn init, add --overwrite once: init wrote its own components/ui/button.tsx and lib/utils.ts, and Fine's versions replace them (icon-button and dialog build on Fine's button API). Fine's cn knows the preset utilities, so h-control-md and h-12 merge.
  5. Load the fonts in the theme item's meta.fonts with next/font, one CSS variable each, passing an entry's axes or weights (as axes and weight) when it lists them: Folio's Newsreader and Poster's Bricolage Grotesque list opsz, and load as a static cut without it. Ledger needs Geist as --font-geist-sans and --font-geist-mono.
  6. App root: <MotionConfig reducedMotion="user"> and one <Toaster />. TooltipProvider is optional.

Done when the page renders in the chosen preset's colors and type and the dev server logs no import errors.

Discovery

Read https://fine-design.qeqx.chatgpt.site/llms.txt for the per-item list (description, docs URL, registry URL). It also has the conventions below in short form.

  • npx shadcn@latest search @fine, then npx shadcn@latest view @fine/<name> for the source and files of one item. Fine items list their exports and variants in meta.
  • The shadcn MCP server (npx shadcn@latest mcp) exposes the same search, view and add to agents. This plugin starts it; elsewhere, add it to the agent's MCP config.
  • Read an item's exports and variants before guessing a prop.

Rules agents get wrong

Tokens. Use semantic and preset utilities only. Surfaces and text: bg-background, bg-surface, bg-muted, text-foreground, text-muted-foreground, border-border, border-input. Fills: bg-primary, bg-secondary, and success, warning, danger, info (each with -foreground, -subtle, -subtle-foreground). Shape and type: rounded-control, rounded-container, rounded-small, rounded-pill; h-control-sm|md|lg; px-pad-control-*, px-pad-field-*, p-pad-container-*; border-line and its directional forms; font-label, font-title, font-strong, font-display; shadow-raised for resting surfaces, shadow-control for a control's own lift (the selected tab) and shadow-overlay for popups. A raw hex, a palette step (bg-blue-500), a fixed height like h-9 on a control, or a literal rounded-md is a bug even where Tailwind's palette still exists: it breaks when the preset changes.

Focus and dark mode. focus-visible:focus-ring on anything focusable. Dark mode is .dark or .light on <html> or any subtree; with neither, the OS decides. dark: follows the same rule. Every preset defines both modes.

Figures. Money, counts, IDs and addresses take the figures utility (the preset's figure face with tabular digits). A stat figure in a card also takes figure-fit, inside a parent that is @container and sets the size (text-xl): the figure keeps that size when it fits and shrinks when the card or the face is too narrow. Set --figure-chars on the grid to the longest figure's length (default 12).

Accent. accent marks emphasis on data. How many a screen carries is the preset's call. Ledger allows one, on the main data element, never on chrome. Every preset keeps its accent (and a chromatic primary) 40 degrees or more of hue from danger, so an accent never reads as an error.

Copy. Write what the user needs to act: the label, the value, the action. A form shows a hint when an input has rules or a format (password length, date pattern): FieldDescription inside Field, stating the rule and nothing else. Whether a screen also has taglines or secondary labels follows its direction.

Ledger

Ledger's decided look, for Ledger and nothing else: ink chrome (primary, focus ring), grey secondary, cobalt accent on a screen's main data element only, Geist plus figures, 6px and 8px radii, flat at rest. No taglines, secondary labels or explanatory helper text, except a FieldDescription on an input with a rule or format. No gradients, neon, decorative color or alternative typefaces.

Making a preset

  1. Copy scripts/presets/ledger.mjs to scripts/presets/<name>.mjs in the Fine repo. name equals the file name; every key is required (palette, semantic light and dark, fonts, weights, text, radius, borderWidth, control, padding, shadows); fontOptions is optional.
  2. Write each non-contract font as var(--font-<id>, "<Family>") and add its next/font/google loader (variable: "--font-<id>", preload: false) to site/presets.ts. If a face needs axes or a fixed weights list, declare it in fontOptions under its variable and pass the same axes or weight in the loader; the registry build throws when a font has no loader or the options differ.
  3. Run npm run tokens. Every pair must pass: text 4.5:1, input and ring borders 3:1, accent 3:1 on background and surface, accent and a chromatic primary 40 degrees or more from danger in hue, all colors inside sRGB. Give the accent a ramp of its own in palette.hues if it is too close to red. Fix the values, not the gate.
  4. npm run build derives theme-<name>; npm run verify:install proves it installs and renders.

A preset cannot change roles, keyboard paths, validation, motion tiers or the focus ring.

Variant API

  • variant and size props via cva; defaults live in each file's defaultVariants. Button variants: primary, secondary, outline, ghost, danger; sizes sm, md, lg. loading keeps the label width and blocks clicks.
  • Each <name>Variants() export styles another element: <a className={buttonVariants({ variant: "outline" })}>. render={<a href="/x" />} swaps the element. Merge classes with cn from @/lib/utils.
  • Badge and Alert share neutral plus the four statuses. IconButton requires label.

Which component

JobUseNot
Blocking decision or short formDialogDrawer
Secondary panel, filters, mobile navDrawerDialog
Anchored detail or small formPopoverDialog
One value, short listSelectCombobox
One value, long list with searchComboboxSelect
Actions on an itemDropdownMenuSelect
Global actions by keyboard (Meta+K)CommandPaletteDropdownMenu
Persistent message in the pageAlertToast
Transient confirmationtoast.add({ title, type })Alert
Status of a recordBadgeTag
Chosen value or filter, removableTagBadge
Same-page panelsTabsSidebar
Site or app navigationNavbar, Sidebar, Breadcrumb, PaginationTabs
Form with validationForm, Field, FieldLabel, FieldErrorbare Input
Rule or format for an inputFieldDescription inside FieldPlaceholder text, Tooltip
Copy a link, key or IDCopyButtonIconButton with your own clipboard code
Delete or discard one item without a modalConfirmButtonDialog (keep Dialog for several fields or consequences)
Autosave, sync or background work: saving, saved, failedAsyncStatusToast, a hand-made spinner
Verification code, 2FA or PINOtpInputOne Input per digit
Password entryPasswordInputInput with type="password"
Progress through a multi-step flowStepperTabs, Progress
Todo or setup steps being completedChecklistLoose Checkboxes
Like, star, bookmark or upvote with a countReactionButtonButton plus AnimatedNumber by hand
Unread count on a bellNotificationBellIconButton with a Badge
Content whose height changes (steps in a Dialog or Drawer, expanding forms)AutoHeightAnimating height by hand

Blocks (auth-form, hero, feature-grid, pricing, faq, footer, dashboard-shell) compose components/ui only. Install one as a start, then edit it.

Motion

Static is the default. Add motion only when a component already ships it, a source animation maps onto a tier, or it is the one change the user needs to notice. Alert, Badge, the Navbar wordmark, a Tag outside TagList, and slider drag and key steps stay static: a state change there is read from the new label, and animating them is a regression.

Pick the tier by what moves; the bigger the thing, the slower the tier.

TierEnterExitUse
fast80ms60mshover, focus, check and radio marks, tooltips, hover highlight, avatar image fade, tag removal exit
moderate160ms120msselect, combobox, menu and popover enters, drawers, tab and pagination indicators, switch thumb, rolling digits, tag sibling glide, slider track-press glide
slow240ms, bounce 0.12160msdialogs, command palette
expressive420ms visual, bounce 0.28160msfeedback arriving: toasts and the hero slips. The one overshoot
  • Motion JS: enter on spring.<tier>, exit on spring.<tier>.exit with easing.exit, both from @/lib/motion. CSS: duration-(--duration-<tier>) with ease-spring-<tier> to enter; duration-(--duration-<tier>-exit) with ease-exit to leave. Use these tokens in place of invented durations or bounce values.
  • Lists, menus and nav share one hover highlight: useFluidHover and <FluidHighlight> from @/lib/fluid-hover. Popups use popupSurface, popupMotion, popupItem from @/lib/popup.
  • Animate transform and opacity. Width moves only where size is the information (progress fill, switch thumb, highlight, a figure gaining a digit, slider position).
  • Fine's own (original): AnimatedNumber digit roll (also the pricing price), TagList removal exit and sibling glide, Slider track-press glide, Avatar image fade. Use AnimatedNumber for a figure that changes while on screen; wrap removable Tags in TagList.
  • Ready-made motion for everyday changes, from 0.4. Use these instead of animating by hand: CopyButton (drawn check, then reverts), AsyncStatus (spinner, check or X, label rolls), AutoHeight (height glides; pass transitionKey to crossfade swapped views, padding on the children), ConfirmButton (widens into the question), ReactionButton (fill, press, rolling count), NotificationBell (swings once when count rises, the one overshoot), PasswordInput (reveal swap, strength meter from strength 0 to 4 or a scorer), OtpInput (slots roll, ring slides, invalid shakes, state="success"), Checklist (strike line, moveCompletedToEnd glides the item), Stepper (check draws, connector fills, ring moves). Each is static on first render and falls back to fades under reduced motion. Never add loops or page-load entrances.
  • Reduced motion drops travel and keeps fades: MotionConfig reducedMotion="user" for Motion, motion-reduce: for CSS.

Accessibility contracts

  • Base UI supplies roles, keyboard and focus. Keep its parts; re-implementing them breaks the tested paths (dialog focus trap and return, menu arrows, tabs Home/End, combobox label focus).
  • Combobox goes inside Field with a FieldLabel before it; the label focuses the input.
  • FieldDescription goes between the control and FieldError; Base UI links it to the input through aria-describedby, so the hint is read with the label.
  • Mount <Toaster /> once, then call toast.add({ title, type }) from anywhere.
  • Items that change state keep the accessible name in step with the visuals: CopyButton, ReactionButton and NotificationBell rename themselves in the commit that changes the state, and AsyncStatus is a polite role="status". Do not wrap them in your own live region or relabel them mid-animation.
  • OtpInput is one real input, so give it a FieldLabel inside Field; PasswordInput takes a FieldDescription beside its strength label; ConfirmButton moves focus to Cancel on open and back to its trigger on Cancel, Escape or confirm; Checklist items need stable keys; Stepper marks the current step with aria-current="step".
  • Icon-only controls take label (IconButton). Danger Alert uses role="alert", the others role="status".
  • Every preset keeps text pairs at 4.5:1 and input borders at 3:1; take colors from tokens and the contrast holds.

Frequently asked questions

What does the Fine Design AI skill do?

Use when building or restyling React UI in a project that uses Fine (fine-design, @fine/ components, theme-ledger, theme-folio, theme-poster), or when asked to install or use Fine components. Fine is a shadcn registry on Base UI, Tailwind v4 and Motion. Behavior is the same everywhere; appearance is a preset (Ledger, Folio, Poster).

Why use Fine Design on TypingMind?

Because you install it once and use it with any model. Fine Design is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Fine Design in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/anon5376/fine-design/tree/main/plugin/skills/fine-design. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Fine Design?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Fine Design?

As many as you like. As long as a model supports skills, you can use Fine Design with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Fine Design AI skill free?

Yes. It is published on GitHub by anon5376 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇