Skip to content

About

Neo-brutalist React components with hard edges: 2px ink borders, hard offset shadows, flat lime and pink brights, and every interactive state styled.

Topics

Resources

Stars

13 stars

Watchers

0 watching

Forks

Repository files navigation

stream/ui

Neo-brutalist React components with hard edges: 2px ink borders, hard offset shadows, flat lime and pink brights, and every interactive state styled.

This repo holds two things:

  • @streamuilib/react, the component library published to npm
  • The docs site, a Next.js app that showcases and documents every component, page section, icon, and experiment, and uses the package itself
bun add @streamuilib/react

Docs and live examples: streamui.org. Setup and usage for the package are in packages/react/README.md.

What's in the library

Part What you get
Components Button, Badge, Card, Alert, Input, Textarea, Select, Checkbox, Radio Group, Switch, Slider, Tabs, Accordion, Dialog, Tooltip, Progress, Battery, Skeleton, Avatar, Audio Player, Track List, Equalizer, and Animated Icon, each in two designs: Classic (hard borders and offset shadows) and Comic (hand-inked outlines, halftone dots, starbursts, and sound effects). Plus a pure-CSS 3D Cube, solid, lined, or beveled. Keyboard support and focus states included.
Sections Hero, Features, Pricing, Testimonials, FAQ, and Footer, built from the components. They size themselves with container queries, so they fit a full page or a narrow column.
Icons The full Lucide set, searchable, with size, stroke, and animation controls. Click an icon to copy its JSX.
Animated icons Wrap any SVG icon in <AnimatedIcon> to draw, spin, bounce, wiggle, pulse, shake, or pop it on hover, on a loop, or once. Pure CSS, off under reduced motion.
Labs Interaction experiments that haven't graduated into the library yet.

Install with shadcn

Every component, section, and lab is also a shadcn registry item, so you can copy the source straight into a project that uses shadcn/ui:

# See everything in the registry
bunx shadcn@latest search https://streamui.org/r/registry.json

# Add an item (it brings the theme and anything else it needs)
bunx shadcn@latest add https://streamui.org/r/flappy-hero.json

Or register the namespace once and use short names:

bunx shadcn@latest registry add "@streamui=https://streamui.org/r/{name}.json"
bunx shadcn@latest search @streamui
bunx shadcn@latest add @streamui/flappy-hero

npx works the same as bunx.

Files land in streamui/ folders (components/ui/streamui/button.tsx, lib/streamui/cn.ts, ...), beside your own shadcn/ui components, never over them. theme adds the tokens and utilities; fonts adds Archivo Black, Space Grotesk, and Space Mono. The full catalog is at https://streamui.org/r/registry.json.

The registry is generated from the real sources on every build (bun run registry:build, see scripts/build-registry.ts), and tests/shadcn-registry.test.ts validates it against shadcn's schema.

Getting started

Requires Bun 1.3 or later.

bun install
bun dev

Open http://localhost:3000. bun dev builds the package first, then starts Next.js.

To work on the package and the site together, run the package in watch mode in a second terminal so your edits rebuild automatically:

bun run ui:dev

Configuration

Deployment settings come from environment variables, so nothing personal or deployment-specific is committed to this public repo. All of them are optional; the site builds and runs with none set.

cp .env.example .env.local
Variable Purpose
NEXT_PUBLIC_SITE_URL Canonical origin for links, the sitemap, and share images. Defaults to https://streamui.org.
FUNDING_GITHUB_SPONSORS_URL GitHub Sponsors profile shown on /sponsor, e.g. https://github.com/sponsors/Sohan-Rout
FUNDING_RAZORPAY_QR_URL Image URL of a Razorpay UPI QR code, shown on /sponsor for scanning
FUNDING_RAZORPAY_URL Razorpay payment link, shown as a button for people paying on their phone

Values are validated at build time: a malformed or non-https link fails the build with a message naming the variable. In production, set them in your host's dashboard (on Vercel: Project Settings → Environment Variables) and redeploy. .env* files are gitignored, and a test fails if one is ever committed or if a credential appears in any tracked file.

Scripts

Script What it does
bun dev Builds the package, then starts the dev server
bun run build Builds the package, then the production site
bun start Serves the production build
bun run lint Runs ESLint
bun run typecheck Type-checks the site and the package
bun run test Builds the package, then runs every test
bun run check Lint, typecheck, test, and build: everything CI runs
bun run ui:build Builds @streamuilib/react into packages/react/dist
bun run ui:dev Rebuilds the package on every change

Project structure

packages/react/          @streamuilib/react: components, AnimatedIcon, theme.css
  build.ts               Bun build: per-file ESM, types, theme
src/
  app/
    page.tsx             home page
    (docs)/              /components, /sections, /icons, /labs and their detail pages
  components/
    blocks/              home page sections and site chrome (header, footer)
    sections/            the page sections shown under /sections
    docs/                docs UI: code blocks, examples, props tables, navigation
    demos/               home page demos and Labs experiments
    ui/                  site-only layout pieces (Section, Rail, SectionHeading)
  examples/<slug>/       one file per docs example
  registry/              the list of components, sections, and labs the docs are built from
  lib/                   helpers: site config, SEO, share images, highlighting, funding

How the docs work

The src/registry/ files list every component, section, and lab. Each docs page, sidebar link, index card, and previous/next link is generated from them.

Docs never paste code by hand. Each example in src/examples/ is both the live preview and the source shown under it, and every "Source" panel reads the real file at build time. Code is highlighted on the server with Shiki, so it adds no JavaScript to the page.

Adding a component

  1. Write it in packages/react/src/Name.tsx and export it from packages/react/src/index.ts.
  2. Run bun run ui:build.
  3. Add one or more example files under src/examples/<slug>/.
  4. Add an entry to src/registry/components.ts with its examples, props, and accessibility notes.

The page at /components/<slug> and its navigation links appear automatically. Sections and labs work the same way with their own registry files.

The registries hold data only: names, props, and file paths, never component imports. Importing a component there would ship its code to every page that reads the registry, the docs sidebar included. Pages render examples, sections, and labs with <Live file="..." />, which loads only the files a page shows. bun run live:build regenerates the map behind it (src/registry/live.generated.tsx); bun dev and bun run build run it for you, and a test fails if it's stale.

Staying light

  • Each page loads only the code for the examples, sections, and labs it shows.
  • The Components, Sections, Labs, and Icons lists render a first batch and load more as you scroll (with a Show more button for keyboards), so their live previews load and animate only once they're reached.
  • Cards off screen skip rendering (content-visibility: auto).
  • Links prefetch on hover, focus, or touch instead of on sight, and not at all when the visitor has Save-Data on or a 2G connection.

Testing

Tests use bun test with Testing Library on a happy-dom DOM.

bun run test
Suite What it protects
packages/react/test/*.test.tsx Component behavior as users and screen readers see it: roles, states, keyboard navigation, form submission
packages/react/test/build.test.ts The published output: "use client" on line 1 of client modules only, .js import extensions, production JSX, complete exports, peer ranges
tests/registry.test.ts Every docs page: unique slugs, real source files, examples, package exports, navigation
tests/live-map.test.ts The registries stay data-only, and the generated live map is up to date
tests/render.test.tsx Every example, section, and lab mounts without crashing, with no duplicate ids
tests/seo.test.ts Canonical URLs, share-card metadata, sitemap, robots, manifest
tests/dice.test.tsx The die always lands on the rolled face, opposite faces sum to 7, rolls cover 1 to 6
tests/env.test.ts Environment validation: defaults, https-only links, clear errors
tests/secrets.test.ts No .env files or credentials (tokens, keys) committed to the public repo
tests/funding.test.ts, tests/helpers.test.ts Sponsor links, shape roller, icon names copied from the icon browser

CI runs lint, typecheck, tests, and a full build on every push and pull request. Publishing the package also runs its tests first.

Design system

Design tokens live in packages/react/src/theme.css and are shared by the package and the site:

  • Surfaces: near-white paper in three levels (raised, base, sunken)
  • Ink: one near-black for text, borders, and shadows
  • Brights: lime (primary), hot pink (secondary), with blue, violet, and orange as sparing accents, plus soft tints for large areas
  • Shadows: hard offsets (shadow-brutal-sm, shadow-brutal, shadow-brutal-lg). Buttons lift toward the light on hover and sink into their shadow on press.
  • Type: Archivo Black for display, Space Grotesk for body copy, Space Mono for labels and code

The theme is light only.

Tech stack

Publishing the package

See Publishing to npm in the package README.

Launch videos

Short launch videos come from the third-party /brag agent skill. The skill is not committed: it bundles about 18 MB of audio, so .agents/ and .claude/skills/brag are gitignored. skills-lock.json records the version in use.

To set it up in a fresh clone:

# Install the skill into .agents/skills/brag
bunx skills add https://github.com/latent-spaces/brag --skill brag

# Link it where Claude Code looks for project skills
ln -s ../../.agents/skills/brag .claude/skills/brag

With the dev server running (bun dev), ask your agent to /brag. The video, poster, and share copy land in brag-output/, which is also gitignored.

Support

stream/ui is free and open source. If it saves you time, you can support its development at streamui.org/sponsor (GitHub Sponsors or UPI), or star the repo.

Sponsor links come from the FUNDING_* environment variables (see Configuration); unset ones are hidden.

License

The @streamuilib/react package is MIT licensed © Sohan Rout.

About

Neo-brutalist React components with hard edges: 2px ink borders, hard offset shadows, flat lime and pink brights, and every interactive state styled.

Topics

Resources

Stars

13 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages