Introduction
Rime is a set of React components themed entirely by CSS custom properties: CSS Modules, no Tailwind and no component library underneath. A project keeps the components and swaps one theme file. 69 components are documented (32 in full), each with live examples, its API generated from the source, the tokens it reads, accessibility notes and rules.
What Rime is
Rime installs like shadcn/ui: you copy the source into your project with the shadcn CLI and own it from then on. Unlike shadcn, every component is a folder with a .tsx file and a CSS Module, and every visual decision is a token. Two presets ship (Rime Default, frosted glass in Frost blue, and Rime Flat), each in light and dark mode. Rime Studio turns any brand into a theme.css.
It is built for AI agents as much as people: every page has a markdown twin, the whole site is in /llms.txt, and the registry works with the shadcn MCP server.
Quick start
In a Next.js App Router project with the @/* path alias, add the base styles and everything:
npx shadcn@latest add KezLahd/rime/kitThen import the styles first in app/globals.css, and wrap the app in ToastProvider:
@import "./styles/tokens.css";
@import "./styles/base.css";
@import "./styles/shadcn-bridge.css";
@import "./styles/theme.css"; /* optional: your theme from Rime Studio */Full steps, single components and the manual route are in Installation.
The rules
- Import primitives from "@/components/ui" (the barrel). Shells come from "@/components/shell/*".
- Never restyle a primitive from a screen. Theme it with CSS custom properties (tokens) instead: system tokens in app/styles/tokens.css, per-component tokens (--button-radius, --input-height-md, --table-head-fill) at :root or on a wrapper.
- CSS Modules only. No Tailwind, no inline colour values, no new component library.
- No heavy rounding beyond the theme's scale, no scale-up or lift on hover, no bento grids, no left accent bars, no decorative background effects that do not derive from the product.
- No eyebrow or small label stacked over a title. Text uses the full width of its column: no narrow measure caps.
- Summary stats are one card with hairline cells, never a grid of separate stat cards.
- Filters are dropdowns (Select chips) plus one full-width search, never a row of toggle chips. Sortable table headers are the whole cell; pagination is centred under the table.
- One primary button (the brand gradient) per view. One table look everywhere. Modal and sheet headers keep one left edge.
- Every list page is GlassPanel > FilterBar + Table + Pagination, with nothing above it.
- Every component needs its loading, empty, error and disabled states; an empty state always says what to do next.
- Text contrast 4.5:1 minimum (3:1 for focus rings and control edges). Fill colours like --brand-soft and --danger-base are never text.
- In Next.js, gate access inside page.tsx, never in layout.tsx (a layout gate leaks the page into the RSC payload).
- No em dashes in copy.
Where next
- Components: every component as a live card, filterable by category.
- Theming and Rime Studio: make a theme for your brand.
- AI agents: llms.txt, the registry, the MCP server and the Claude skill.
- Coming from shadcn: the name map and the variable bridge.