I didn't set out to build a component library. I set out to stop rewriting the same button.
Every project I started, the same thing happened. I'd need a button that felt alive. A marquee of logos. A number that counts up when it scrolls into view. Small things. And every time, I'd open the last project, find the component, copy it, and then spend an hour fixing the parts that only worked in that project. The easing was hardcoded. The animation stuttered on the exit. The dark mode was an afterthought I'd bolted on at 2am.
So I started collecting them properly. Not to ship a product. Just so I'd stop paying the same tax over and over. GodUI is what that pile turned into once I got serious about the details.
A quick tour of GodUI components and their motion.
Why bother animating anything
Here's the thing nobody tells you about animation: most of it is bad because it's decoration.
Someone adds a bounce because a bounce looks fun in isolation. Then you use the interface for real, ten times a minute, and the bounce is a small tax on your attention every single time. Motion that draws attention to itself is motion that gets in your way.
Good motion does the opposite. It answers questions you didn't know you were asking. Where did this panel come from? Is this thing loading or broken? Did my click register? A menu that slides out from the button you pressed tells you it belongs to that button. A list where items settle in one after another tells you they arrived in order. You don't read any of that consciously. You just feel like the interface makes sense.
That's the bar I care about. Not "does this look cool in a screen recording" but "does this make the interface easier to follow." Every animation in GodUI has to earn its place by that rule. If it's only there to be pretty, it's decoration, and decoration is the first thing that starts to annoy you.
The part I underestimated: a shared language for motion
When I had five components, I could eyeball the animations. When I had fifty, they started drifting. One used a 250ms fade. Another used 300ms. One had a spring that overshot, another eased flat. Individually fine. Together they felt like they were built by different people, because in a sense they were, just me on different days.
The fix was to stop making the decision per component. I pulled every duration, easing curve, spring, and stagger into one file of tokens. Now nothing picks its own timing. A component reaches for DURATION.base or SPRING.snappy and gets the same value as everything else. Change the token, and the whole collection moves together.
Here's roughly what that file looks like, because the actual numbers are the interesting part:
export const DURATION = { fast: 0.15, base: 0.2, slow: 0.3, slower: 0.4 };
export const EASE = {
out: [0.22, 1, 0.36, 1], // decelerate and settle
standard: [0.3, 0.7, 0.4, 1], // the default GodUI curve
back: [0.3, 0.7, 0.4, 1.5], // same curve, but it overshoots
inOut: [0.65, 0, 0.35, 1], // symmetric, for loops
};
export const SPRING = {
smooth: { stiffness: 320, damping: 32, mass: 0.9 }, // surfaces, dialogs
crisp: { stiffness: 500, damping: 40 }, // accordions
snappy: { stiffness: 520, damping: 32 }, // menus, popovers
bouncy: { stiffness: 170, damping: 12, mass: 0.1 }, // docks, magnetic pops
};
None of those numbers are round, and that's the point. 0.2s for a base move isn't a guess. Enter is calmer than exit because appearing and disappearing don't deserve the same weight. A menu wants snappy so it feels instant. A dialog wants smooth so it feels like a heavy thing settling. The back curve is literally the standard curve with the last number pushed past 1 so it overshoots a hair before landing. Small distinctions, but they're the difference between "this feels designed" and "this feels like defaults."
I didn't invent those values. That would've been arrogant and probably wrong. The durations track Material 3's scale. The spring presets mirror the overshoot and subdued schemes from Material 3 Expressive. The twelve principles behind them go back further, to Disney's animation canon reapplied to interfaces. There's decades of work on how motion should feel, and ignoring it to freestyle my own curves would've just meant relearning what people already know.
The twelve principles, and what each one actually means
I keep saying "twelve principles" like it's a slogan. It isn't. They're the checklist I run every component through before it ships, and each one killed a version of something at some point. Here's the whole list, in plain terms.
Clarity. One focal change at a time. If two things move at once and neither is clearly the star, the eye doesn't know where to look and the motion becomes noise. Most of my early animations failed here.
Continuity. Things move along a visible path instead of teleporting. A panel that jumps from nowhere to somewhere makes you reconstruct what happened. A panel that slides means you never lost the thread.
Hierarchy. Sequence tells you what matters. The primary element leads, the rest follow. When everything animates on the same frame, everything reads as equally important, which means nothing does.
Spatial awareness. Elements enter and exit from where they actually live. A dropdown grows out of its trigger. A drawer comes in from the edge it's attached to. Motion that respects the layout keeps your mental map stable.
Feedback. The interface answers every input immediately. Before anything loads or transitions, the click has to register. A button that reacts the instant you press it feels alive even if the real work takes a second.
Timing and easing. The curve is the character. Nothing in the real world moves at a constant speed, so nothing in the interface should either. This is where those cubic-bezier values earn their keep. Linear motion is the tell of something unfinished.
Anticipation. A tiny wind-up before a move. It primes your eye so the action feels intentional instead of abrupt. This one's subtle to the point of invisible, which is exactly when it's working.
Follow through. Motion doesn't stop dead. Trailing elements keep going a beat longer and settle, which is what gives a thing weight. It's the bouncy spring, and it's why a dock icon feels physical instead of scripted.
Rhythm. When many things move, they move on a consistent cadence. That's the stagger tokens: 0.03s, 0.05s, 0.08s between children. Coordinated delay turns a dozen moving parts into one gesture instead of a pile-up.
Restraint. The best motion is felt, not noticed. When I can't decide, I do less. Every flashy idea I've killed made the component better, without exception.
Performance. Animate only transform and opacity, keep it at 60fps, and keep springs interruptible so you can grab a thing mid-flight. Motion that stutters is worse than no motion. This is a hard rule, not a preference.
Accessibility. Honor prefers-reduced-motion. Drop the transforms, keep a soft opacity change, and the interface still reads perfectly. Motion should never be load-bearing for someone who's turned it off.
Read them back and you'll notice they're not really twelve separate ideas. They're one idea, motion should serve understanding, sliced twelve ways so I can catch the specific way a given animation is failing.
The unglamorous payoff: the guidelines pages and the components read from the exact same token file. Not a copy. The same export. So the documentation can't describe one thing while the components do another. They physically can't drift, because there's only one source of the truth.
Building it so an agent can use it
This is the part that changed how I think about the whole thing.
Most component libraries assume a human is browsing the docs, finding a component, reading the install command, and copying it. That flow is fine. But increasingly the thing sitting between me and my code is an agent. And an agent browsing a docs site by scraping HTML is a bad experience for everyone.
So GodUI ships an MCP server. Model Context Protocol is the standard for handing tools to an AI IDE, and the GodUI server gives the agent exactly three:
list_componentsto see the whole catalogsearch_componentsto find one by what it does, in plain languageget_componentto pull a single component's install command and full source
You add the server to Cursor, or Windsurf, or Claude, once. Then you type "add a GodUI magic button" or "give me a marquee of logos" and the agent finds it, gets the real install command, and writes the source into your project. No copy-paste. No hunting the docs.
The detail I'm quietly proud of: the server fetches the live registry every time. There's no bundled snapshot of components to go stale. Publish a new component and every agent that has the server installed can use it immediately, with zero update on their end.
Open source, and why you own the code
GodUI is MIT licensed, and it's distributed as a shadcn registry. That second part matters more than it sounds.
Most libraries you install as a dependency. The code lives in node_modules, hidden behind a version number, and when you want to change how a component behaves you're fighting the abstraction. A shadcn registry works the opposite way. When you add a component, the source gets copied straight into your project. It's your file now. Rename it, gut it, restyle it, delete half of it. There's no version to fight and no maintainer to wait on.
If you already use shadcn/ui, it's the same flow you know. Add the @godui registry to your components.json, then pull components by name:
pnpm dlx shadcn@latest add @godui/magic-button
Under the hood the project is a monorepo, and each piece does one job:
componentsis the real library, built with React, TypeScript, Tailwind v4, and Motion. It's the single source of truth, tokens and all.mcpis the server that lets agents discover and install components by description.clihandles the registry tooling.docsis the documentation site with live previews.storybookis where components get built and stress-tested in isolation.
Roughly a hundred components live in there now. Every one of them themed with CSS variables, so light and dark work with no extra config, and typed end to end so your editor actually helps you.
Where this leaves me
I still build things for myself first. That hasn't changed, and I don't think it should. The best test of whether a component is good is whether I reach for it on my own projects without wincing.
What surprised me is how much the constraints made it better. Forcing every animation to justify itself killed a lot of stuff that looked clever and felt annoying. Forcing every timing through one token file made the whole collection feel like one thing. And building for agents forced a kind of honesty, because an agent can't be charmed by a nice docs page. It just needs the component to be findable and the source to be correct.
If any of this sounds useful, it's all open. It lives at godui.design. Take what you need, own every line, and change whatever I got wrong.
