npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ryme-ui

v0.2.6

Published

Ryme marketing-site SDK: full design system + UI components. Grainient, side lines, grid strips, section diamonds, layout (header/footer/section head), 45+ shadcn-style components, cn, useIsMobile.

Readme

ryme-ui

The official Ryme design-system SDK. One package reproduces the complete look, layout and component set of the Ryme marketing site — drop it into any React project and the entire design system comes with it:

  • Visuals — Grainient (WebGL animated gradient), SideLines, GridStrip, RuleGrid, GridPattern, SectionBorder
  • Layout — SiteHeader, SiteFooter (router-agnostic via linkComponent), SectionHead, RymeMark
  • UI — 45+ shadcn-style components (Button, Card, Dialog, Sheet, Select, Sidebar, Chart, Calendar, …) pre-themed for the Ryme dark look
  • Utilities — cn, useIsMobile
  • Design system — one self-contained CSS file with all Tailwind v4 tokens, custom utilities and animations

Table of contents


Requirements

  • React >= 18 and react-dom >= 18 (peer dependencies)
  • Tailwind CSS v4 in your project (the stylesheet is built with Tailwind v4 syntax)
  • WebGL 2 support for the Grainient visual (all modern browsers)

Everything else — Radix primitives, class-variance-authority, tailwind-merge, ogl, lucide icons, Recharts, Sonner, etc. — is a declared dependency and installs automatically.

Install

# npm
npm install ryme-ui

# bun
bun add ryme-ui

# pnpm / yarn
pnpm add ryme-ui
yarn add ryme-ui

The package ships a pre-built dist (ESM + .d.ts). Because the published dist is committed to npm, no build step runs on install in published versions. As a git dependency the prepare script builds it automatically:

bun add github:Ryme-Labs/ryme-ui
npm install github:Ryme-Labs/ryme-ui

Quick start

// main.tsx (or your app entry)
import "ryme-ui/styles.css";

// Any page:
import {
  Button,
  Grainient,
  GridStrip,
  RuleGrid,
  SectionBorder,
  SectionHead,
  SiteFooter,
  SiteHeader,
  SideLines,
} from "ryme-ui";
import { Link } from "react-router"; // or any router — see linkComponent

export function Page() {
  return (
    <div className="flex min-h-screen flex-col">
      <SiteHeader linkComponent={Link} />

      <main className="flex-1">
        <div className="relative">
          <GridStrip side="left" edgeCut />
          <GridStrip side="right" edgeCut />
          <SideLines />

          <section className="relative flex min-h-screen items-center overflow-hidden">
            <div className="absolute inset-0">
              <Grainient color1="#EF4444" color2="#B91C1C" color3="#000000" />
            </div>
            <div className="relative mx-auto max-w-6xl px-5 py-24 sm:px-8">
              <SectionHead id="hero" label="Your label" title="Your headline." />
              <Button asChild className="mt-8">
                <Link to="/demo">Get started</Link>
              </Button>
            </div>
          </section>
        </div>
      </main>

      <SiteFooter noBorder linkComponent={Link} />
    </div>
  );
}

Package structure

ryme-ui/
├── src/
│   ├── index.ts              # public entry — everything is re-exported here
│   ├── ryme-ui.css           # design system: tokens, utilities, visuals CSS
│   ├── cn.ts                 # cn() — clsx + tailwind-merge
│   ├── use-mobile.tsx        # useIsMobile() — < 768px hook
│   ├── layout/               # SiteHeader, SiteFooter, SectionHead, RymeMark
│   ├── ui/                   # 45+ shadcn-style components (Radix-based)
│   └── visuals/              # Grainient, GridStrip, RuleGrid, SectionBorder,
│                             # SideLines, GridPattern
├── dist/                     # build output (ESM + .d.ts + ryme-ui.css)
├── vite.config.ts            # library build config
└── package.json

Imports are resolved from the package root:

import "ryme-ui/styles.css"; // the full design system CSS
import { Button, Grainient } from "ryme-ui"; // components

Design system

The entire Ryme look lives in one CSS file: ryme-ui/styles.css. It is a Tailwind v4 stylesheet (@import "tailwindcss") that defines the theme tokens, base layer, custom utilities (label-mono, marquee) and every ryme-* class used by the visuals. Import it once at your app root — do not import it per page.

Theme tokens

Colors are defined in :root as oklch values and exposed to Tailwind utilities via @theme inline (so bg-primary, text-muted-foreground, border-border, … all work).

| Token | Default value | Used for | | --- | --- | --- | | --background | oklch(0.13 0.008 20) | Page background (near-black warm) | | --foreground | oklch(0.94 0.004 60) | Primary text | | --card | oklch(0.16 0.009 20) | Cards, form fields, panels | | --card-foreground | oklch(0.94 0.004 60) | Text on cards | | --popover / --popover-foreground | card values | Dropdowns, menus, sheets | | --primary | oklch(0.57 0.21 26) | The Ryme red — accents, buttons, diamonds | | --primary-foreground | oklch(0.98 0.005 60) | Text on primary | | --secondary / --secondary-foreground | dark warm | Secondary surfaces | | --muted | oklch(0.19 0.008 20) | Muted surfaces | | --muted-foreground | oklch(0.66 0.012 30) | Secondary text, labels | | --accent / --accent-foreground | warm red-tint | Hover states | | --destructive | primary red | Destructive actions | | --border | oklch(0.26 0.012 25) | All borders, hairlines | | --input | border value | Form field borders | | --ring | primary red | Focus rings | | --chart-1 … --chart-5 | red/warm ramp | Chart component palettes | | --sidebar* | background ramp | Sidebar component palette | | --radius | 0.25rem | Global radius scale seed |

ryme-* visual tokens

The visuals read their own CSS custom properties so every color/position can be overridden per project:

| Token | Default | Used by | | --- | --- | --- | | --ryme-background | var(--background) | Grid strip edge-cut lines | | --ryme-primary | var(--primary) | Section diamonds | | --ryme-border | var(--border) | Side lines, section border line | | --ryme-grid-line | oklch(0.22 0.01 25) | RuleGrid hairlines | | --ryme-grid-color | rgba(156,163,175,0.15) | GridStrip grid | | --ryme-grid-pattern-color | rgba(156,163,175,0.3) | GridPattern SVG | | --glow-red | red glow shadow | Optional glow effects |

Fonts

  • Sans: Inter Tight (falls back to system-ui)
  • Mono: JetBrains Mono (falls back to ui-monospace)

Mapped as --font-sans / --font-mono, so font-mono, font-sans utilities work. Load them yourself (Google Fonts or self-hosted); the package does not fetch fonts.

Custom utilities

  • label-mono — the signature Ryme micro-label: JetBrains Mono, 0.6875rem, 0.16em letter-spacing, uppercase, muted color. Used everywhere from section labels to field captions.
  • marquee — 45s linear infinite horizontal marquee (translateX 0 → -50%); pauses on hover. Disabled automatically under prefers-reduced-motion.

Breakpoints & layout math

The layout is built around a 72rem content measure (max-w-6xl = 72rem) with elements that anchor to its edges:

| Element | Visible at | Position | | --- | --- | --- | | GridStrip (left/right) | ≥ 80rem | calc(50% - 36rem - 28px) wide, flush to viewport edge | | SectionBorder diamonds + line | ≥ 80rem | diamonds at calc(50% ± 36rem) and ± 36rem + 28px; line spans 72rem + 56px | | SideLines (4 fixed lines) | always; anchored at ≥ 64rem | outer pair at calc(50% ± 36rem), inner pair 28px inside |

The 28px offset is the distance from the content edge to the outer diamond — all visuals stay optically aligned with max-w-6xl content. SideLines are position: fixed so they never cause horizontal scroll on viewports between 64–80rem; GridStrip and section borders are hidden below 80rem to avoid overflow.

Overriding the theme

Override tokens on :root in your own CSS after importing ryme-ui/styles.css:

:root {
  --primary: oklch(0.55 0.18 150); /* rebrand to green */
  --ryme-grid-line: oklch(0.3 0.05 150);
}

All components and visuals pick the new values automatically because they read the custom properties — no recompilation needed.


Components

Visuals

Visual components are purely decorative (aria-hidden="true"), pointer-events-none, and render zero layout by themselves — position them yourself with wrappers.

Grainient

A full-screen WebGL 2 animated gradient: noise-driven rotation, sine warping, three-color blend, film grain, then contrast/gamma/saturation grading. Implemented with ogl (WebGL 2, GLSL ES 3.00) on a single triangle.

<div className="absolute inset-0">
  <Grainient color1="#EF4444" color2="#B91C1C" color3="#000000" />
</div>

It fills its parent (width: 100%; height: 100%) — give the parent a size.

All props are optional with these defaults:

| Prop | Default | Description | | --- | --- | --- | | color1 | #FF9FFC | Top/light blend color | | color2 | #5227FF | Mid color | | color3 | #B497CF | Bottom/dark color | | timeSpeed | 0.25 | Animation speed multiplier | | colorBalance | 0.0 | Shifts the blend edges | | warpStrength | 1.0 | Sine-warp amplitude divisor | | warpFrequency | 5.0 | Warp wave frequency | | warpSpeed | 2.0 | Warp animation speed | | warpAmplitude | 50.0 | Warp strength numerator | | blendAngle | 0.0 | Rotation of the color blend axis (deg) | | blendSoftness | 0.05 | Blend edge softness | | rotationAmount | 500.0 | Noise-driven rotation range (deg) | | noiseScale | 2.0 | Noise frequency | | grainAmount | 0.1 | Film grain intensity (0 = off) | | grainScale | 2.0 | Grain cell size | | grainAnimated | false | Drift the grain over time | | contrast | 1.5 | Output contrast | | gamma | 1.0 | Output gamma | | saturation | 1.0 | Output saturation | | centerX / centerY | 0.0 / 0.0 | Shader-space center offset | | zoom | 0.9 | Zoom into the gradient | | className | "" | Extra classes on the wrapper |

Performance notes (all built-in, no work needed):

  • One WebGL context per mount, created once and reused across prop updates (uniform writes only — zero GPU rebuilds).
  • Animation pauses when the element scrolls out of view (IntersectionObserver) and when the tab is hidden (visibilitychange).
  • dpr capped at 2, antialias: false (gradient + grain don't need AA).
  • Cleanup on unmount: context, observers, listeners and canvas are all removed.
  • Respects prefers-reduced-motion via the global CSS base (smooth-scroll/marquee only — WebGL animation itself is user-configurable).

GridStrip

Inset side grid panels that flank the content on wide screens.

<GridStrip side="left" edgeCut />
<GridStrip side="right" edgeCut />

| Prop | Type | Default | Description | | --- | --- | --- | --- | | side | "left" \| "right" | "left" | Which viewport edge | | edgeCut | boolean | true | Add a background-colored 40px edge strip for the cut corner look | | className | string | "" | Extra classes |

Hidden below 80rem; position: absolute — render inside a position: relative wrapper (usually right under <body>/root so it spans the whole page).

RuleGrid

A dense 64px hairline grid overlay with a radial mask, for hero backdrops.

<div className="relative">
  <RuleGrid bleed mask="center" />
  ...content...
</div>

| Prop | Type | Default | Description | | --- | --- | --- | --- | | mask | "center" \| "bottom" \| "none" | "center" | Radial fade (center fades to 75%, bottom anchors at the bottom edge) | | bleed | boolean | false | Extend inset to -2rem so lines run behind overflow content | | className | string | "" | Extra classes |

Opacity is fixed at 0.25; line color comes from --ryme-grid-line.

SectionBorder

A <section> wrapper that draws the Ryme section top border: four rotated diamonds (7px, red, haloed in background + border color) at the content edges, plus an optional hairline.

<SectionBorder line>
  <div className="mx-auto max-w-6xl px-5 py-20">...</div>
</SectionBorder>

| Prop | Type | Default | Description | | --- | --- | --- | --- | | line | boolean | false | Draw the centered hairline between the diamond pairs | | className | string | "" | Extra classes (e.g. relative positioning context) | | children | ReactNode | — | Section content |

Diamonds appear at ≥ 80rem only. SectionBorder renders a <section> — put id / scroll-mt on inner content if you need anchor targets.

SideLines

The four fixed vertical hairlines framing the page (outer pair at the content measure, inner pair 28px inside):

<SideLines />

No props. Renders four position: fixed aria-hidden divs, z-index: 40, pointer-events: none. Anchored to calc(50% ± 36rem) at ≥ 64rem. Place once at the app root, above page content.

GridPattern

An SVG <pattern> rect with optional highlighted "squares" — used for subtle dotted/grid backdrops.

<GridPattern width={40} height={40} x={-1} y={-1} strokeDasharray="0" />

| Prop | Type | Default | Description | | --- | --- | --- | --- | | width / height | number | 40 / 40 | Pattern cell size | | x / y | number | -1 / -1 | Pattern offset | | squares | [number, number][] | — | Cell coordinates to render as filled squares | | strokeDasharray | string | "0" | Dash pattern for the grid path | | className | string | — | Extra classes | | ...props | — | — | Passed through to the <svg> |

Fill/stroke color come from --ryme-grid-pattern-color.

Layout

SiteHeader

The sticky Ryme header: brand mark + wordmark, desktop nav, mobile hamburger with dropdown menu, and a "Book a demo" action button.

<SiteHeader linkComponent={Link} />

| Prop | Type | Default | Description | | --- | --- | --- | --- | | linkComponent | ComponentType<SiteLinkProps> | plain <a> | Router link component (see below) |

SiteLinkProps = { to?: string; hash?: string; className?: string; children?: ReactNode; onClick?: () => void }. Pass your router's Link so internal navigation uses client-side routing; the default renders <a href={to + (hash ? "#" + hash : "")}>.

import { Link } from "@tanstack/react-router";
<SiteHeader linkComponent={Link} />

The nav items are fixed: Workflow, Agents, Skills, Internals (hash links to /), plus /demo. Sticky top, z-50, bg-background/85 + backdrop blur, h-14.

SiteFooter

<SiteFooter noBorder linkComponent={Link} />

| Prop | Type | Default | Description | | --- | --- | --- | --- | | noBorder | boolean | false | Omit the top hairline (for bordered-page layouts) | | linkComponent | SiteLinkComponent | plain <a> | Same router-linking pattern as the header |

Shows the Ryme Labs mark + wordmark, the authorized-testing tagline, and GitHub / X / Demo links (https://github.com/Ryme-Labs/, https://x.com/rymelabs, /demo).

SectionHead

The standard section intro: mono micro-label over a large tight-tracked title.

<SectionHead id="workflow" label="How it runs" title="Five stages. One operator." />

| Prop | Type | Description | | --- | --- | --- | | id | string (optional) | Anchor id (scroll-mt-16 included) | | label | string | The mono uppercase eyebrow | | title | string | The headline |

RymeMark

The geometric block-R SVG logo (viewBox 0 0 256 256, currentColor).

<RymeMark className="h-3.5 w-3.5 text-primary" />

| Prop | Type | Description | | --- | --- | --- | | className | string | Size + color utilities (h-*, text-*) |

Use it for header/footer marks, favicons, loading screens — anywhere the brand mark is needed.

Utilities

cn

clsx + tailwind-merge — the standard class-name combiner. Later classes win, so component overrides work predictably:

cn("px-4 py-2 rounded-md", "px-6"); // → "py-2 rounded-md px-6"

useIsMobile

Reactive matchMedia("(max-width: 767px)") hook. Returns false on the first render (SSR-safe), then the real value once mounted:

const isMobile = useIsMobile();

UI components

45+ shadcn-style components, all re-exported from the package root. They follow the standard shadcn/Radix APIs (variants via class-variance-authority, className merges through cn), pre-themed with Ryme tokens.

| Group | Components | | --- | --- | | Actions | Button (default / outline / secondary / ghost / destructive / link, sm / lg / icon, asChild), Toggle, ToggleGroup, DropdownMenu, ContextMenu, Menubar, NavigationMenu | | Overlays | AlertDialog, Dialog, Sheet, Drawer (vaul), Popover, HoverCard, Tooltip, Command, Sonner (toasts) | | Forms | Input, Textarea, Label, Checkbox, RadioGroup, Select, Switch, Slider, InputOTP, Form (react-hook-form), Calendar (react-day-picker) | | Data display | Card, Badge, Table, Skeleton, Avatar, Separator, AspectRatio, Chart (Recharts), Progress | | Layout/nav | Sidebar, Breadcrumb, Pagination, Tabs, Accordion, ScrollArea, Resizable, Carousel (embla) |

Example — the Ryme look with zero extra styling:

import { Button, Card, CardContent, Input, Label } from "ryme-ui";

<Card>
  <CardContent className="space-y-4 p-6">
    <div className="space-y-1.5">
      <Label>Email</Label>
      <Input type="email" placeholder="[email protected]" />
    </div>
    <Button className="w-full">Continue</Button>
  </CardContent>
</Card>

All components inherit the dark theme automatically — no dark class or provider needed (color-scheme: dark is baked into the base layer).


Guides

Building a hero section

<section className="relative flex min-h-screen items-center overflow-hidden border-b border-border bg-background">
  {/* 1. Grainient backdrop */}
  <div aria-hidden="true" className="absolute inset-0">
    <Grainient color1="#EF4444" color2="#B91C1C" color3="#000000"
      timeSpeed={0.2} warpStrength={1.2} rotationAmount={480} grainAmount={0.08}
      contrast={1.4} zoom={0.9} />
  </div>
  {/* 2. Legibility scrim */}
  <div aria-hidden="true"
    className="absolute inset-0 bg-gradient-to-b from-background/80 via-background/35 to-background" />
  {/* 3. Rule grid with bleed + center mask */}
  <div className="relative mx-auto max-w-6xl px-5 py-24 sm:px-8">
    <div className="relative">
      <RuleGrid bleed mask="center" />
      <h1 className="relative text-5xl tracking-tight sm:text-7xl">
        Recon to report. <span className="text-primary">Proof or nothing.</span>
      </h1>
    </div>
  </div>
</section>

Full marketing page skeleton

export function LandingPage() {
  return (
    <div className="flex min-h-screen flex-col">
      <SiteHeader linkComponent={Link} />
      <main id="main" className="flex-1">
        <Hero />                                {/* raw <section>, see above */}
        <SectionBorder>                         {/* metrics strip */}
          <div className="mx-auto grid max-w-6xl grid-cols-2 px-5 py-8 lg:grid-cols-4">…</div>
        </SectionBorder>
        <SectionBorder line>                    {/* feature blocks */}
          <div className="mx-auto max-w-6xl px-5 py-20 sm:px-8">
            <SectionHead id="workflow" label="How it runs" title="Your headline." />
            …
          </div>
        </SectionBorder>
        <section className="relative overflow-hidden border-t border-border">
          <RuleGrid mask="bottom" />            {/* CTA with bottom-masked grid */}
          …
        </section>
      </main>
      <SiteFooter noBorder linkComponent={Link} />
    </div>
  );
}

Customizing the Grainient

The shader's warp/rotation/grain are independent levers — keep warpStrength ~1–2, rotationAmount 400–600 and grainAmount 0.05–0.15 for the Ryme look; push timeSpeed down for a calmer backdrop, raise contrast for a punchier band.

<Grainient color1="#7C3AED" color2="#C026D3" color3="#0F0A1F" rotationAmount={300} />

Light theme / brand rebrand

:root {
  --background: oklch(0.97 0.005 60);
  --foreground: oklch(0.2 0.02 60);
  --primary: oklch(0.5 0.2 265); /* blue */
  --border: oklch(0.85 0.01 60);
  --ryme-grid-line: oklch(0.8 0.01 60);
}

Accessibility & performance

  • Focus — global :focus-visible ring using --ring; inputs/buttons ship Radix focus handling.
  • Reduced motion — prefers-reduced-motion disables smooth scrolling and the marquee animation via the base layer.
  • Semantics — visuals are aria-hidden; headers render real <nav aria-label>; forms use real labels.
  • Grainient — auto-pauses offscreen/hidden, dpr ≤ 2, single shared context per mount.
  • CSS — Tailwind v4 scans only src/** (@source "../src"), so your CSS output stays small and utility classes are generated on demand.

Browser support

Modern evergreen browsers. WebGL 2 is required for Grainient; the component is a no-op fallback (empty container) where WebGL is unavailable. ES2022 output — transpile for older targets if needed.


Development

bun install          # or npm install
bun run typecheck    # tsc --noEmit
bun run dev          # vite build --watch (rebuild dist on change)
bun run build        # vite build && tsc -p tsconfig.build.json && copy README into dist
  • tsconfig.json — strict ES2022 + DOM, noEmit for typechecking.
  • tsconfig.build.json — emits declarations to dist with rootDir: src.
  • vite.config.ts — library build with preserveModules (per-file output mirrors src/), React + all runtime deps externalized, CSS extracted to dist/ryme-ui.css, sourcemaps off.
  • The only bundled runtime is ogl (used by Grainient); everything else is external.

Publishing

bun run release   # npm version patch && npm publish && git push --follow-tags

prepare and prepublishOnly both run the build, so dist is always fresh. The build also copies README.md into dist/ so the npm page renders it.

Package metadata: name: ryme-ui, license: UNLICENSED, type: module, exports map with "." (ESM + types) and "./styles.css".

Troubleshooting

| Symptom | Cause / fix | | --- | --- | | Grainient shows nothing | Parent has no height — give it absolute inset-0 inside a sized/positioned wrapper, or an explicit height | | Styles missing (components render unstyled) | import "ryme-ui/styles.css" is missing, or imported after your own theme overrides — import it first | | Tailwind classes from ryme-ui components aren't generated | ryme-ui's CSS is pre-built and self-contained; no Tailwind config in your app is required. If your own utilities don't include a class you pass to a component, Tailwind v4 scans your files automatically | | Side lines don't align with content | The 72rem measure assumes max-w-6xl content. Override --ryme-* positions or use a different content width with matching calc() offsets | | SSR hydration warning about Grainient | Grainient mounts WebGL client-side only; it renders an empty div on the server, so hydration is stable | | WebGL context loss on tab switch | Contexts are created per mount and paused offscreen — if you hot-reload aggressively, force a page reload once | | marquee not animating | Verify prefers-reduced-motion is off; the class disables itself there by design | | npm install of git dep fails | prepare needs bun (or npm) to run vite build — ensure devDependencies resolve in your install context |

License

UNLICENSED — private SDK for Ryme Labs projects. See the Ryme-Labs organization for product repos.