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/reactDocs and live examples: streamui.org. Setup and usage for the package are in packages/react/README.md.
| 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. |
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.jsonOr 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-heronpx 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.
Requires Bun 1.3 or later.
bun install
bun devOpen 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:devDeployment 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.
| 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 |
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
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.
- Write it in
packages/react/src/Name.tsxand export it frompackages/react/src/index.ts. - Run
bun run ui:build. - Add one or more example files under
src/examples/<slug>/. - Add an entry to
src/registry/components.tswith 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.
- 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.
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 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.
- Next.js 16 App Router with Cache Components, on React 19
- Tailwind CSS v4, configured in CSS
- TypeScript in strict mode
- Bun for installs, workspaces, scripts, and the package build
- Lucide icons and Shiki highlighting
See Publishing to npm in the package README.
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/bragWith 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.
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.
The @streamuilib/react package is MIT licensed © Sohan Rout.