Build Your Own Lab
5 min read
I highly recommend anyone who works on interfaces has a lab. A scratch pad you go to for making components and tuning interactions, that slowly turns into your own personal library. I revisit mine all the time.
I posted about mine on X and it did way better than I expected, so I pulled the bones out into something you can use. It's called byolab (build your own lab), and it's open source.
Where it came from
Emil Kowalski made himself an interaction lab that generates new interactions every day from rules he set, and he only keeps the ones he likes, so it looks more like him over time. Benji Taylor's Stageshow skill is incredible and was a great base for mine.
But my lab is just a place for me to build components. It's opinionated. I use the components models build to figure out my own taste. I added video exporting in case you want to share stuff, but that's a bonus.
This one is a blank canvas. You make the art.
Ask your agent
You don't really need to read the docs. Open it with your agent and ask how to use it. It checks your setup, starts the lab, and walks you through your first component.
From there, bring whatever you like. Add your favorite UI skills, or tell it to use a certain shadcn component or theme, and it builds on that.
The loop
You ask your agent for something:
make a copy button that shows what it copied
It runs pnpm lab new, builds it, and sends you a link. It shows up in the gallery under "To judge". Click around, try to break it, then keep it or toss it. The agent doesn't get a vote.
Tossing asks why, in one line.
That note goes into TASTE.md. Next time your agent comes up with ideas, it turns the notes into rules and reads them before building anything. Mine has stuff like "product motion stays under 300ms" now, and I stopped getting the same mistakes back.
Leave good notes
Took me a while to figure this one out. The note is the only thing that sticks around, so a lazy one wastes the toss. "looks bad" teaches your agent nothing.
Name the part, say what's wrong with it, and if you know, what you'd want instead:
| Instead of | Try |
|---|---|
| looks bad | spacing is too loose, it reads as a mockup |
| meh | I've seen this toggle a hundred times |
| not practical | clever, but no product would ship a cancel button you drag |
| button is off | the upgrade button floats in the header, put it next to the status it answers |
Say what you liked too. "love the receipt, hate the timer bar" keeps the good half around for next time.
Tuning
It starts from a grid, an idea I got from @MSchwaibold: set the grid first, then design inside it. Mine is 8px with a 24px outer radius, and pnpm lab grid checks every component against it. Tune it, or ask your agent to fit it to your aesthetic.
Some stuff you just can't describe. "a little less bouncy" goes back and forth forever, so DialKit is built in (Josh Puckett made it, it's great). Drag until it feels right, hit Copy, and paste the numbers back to your agent. It bakes them in.
If you want to try different viewports, locales, or times, ask your agent to add knobs by @mertduzgun.
Films
Anything you keep can get a film. You write a few beats (move the cursor here, click this, tween that) and it drives the real component, not a screen recording of it.
beats: [
{ at: 1.4, click: '[data-slot="trigger"]', values: { progress: 1 } },
{ at: 3.6, click: '[data-slot="trigger"]', values: { progress: 0 } },
]Every frame is a function of time, so the renderer steps through it frame by frame into ffmpeg. You get the exact same video every time, light and dark, at whatever size you want:
pnpm lab export copy-button --theme both --height 2160There's also a check that scrubs the film out of order and compares frames, so a stray timer or Math.random gets caught before you render.
Agent first
Every command takes plain arguments, explains its errors, and has a --json flag, since your agent runs them way more than you will:
pnpm lab new <slug> [--kind component|explainer|breakdown]
pnpm lab keep <slug>
pnpm lab toss <slug> --reason "..."
pnpm lab grid <slug>
pnpm lab export <film>grid checks your component against a few hard rules: 8px grid, 24px outer radius, no more than three font sizes. Those are my numbers, swap in yours. It also ships with an AGENTS.md and a few skills, so Claude Code, Codex, Pi, or whatever you use can find its way around.
Make it yours
There are no components in it. TASTE.md starts with a few of my defaults, and you should delete most of them. The grid, the theme, the skills, the way films look, all of it is meant to change.
This lab base is mine, but you should make it yours. No skill is going to give you taste. I read and absorb a lot of other designers' work, there are courses and free resources for it, and I learn a ton from the designers and engineers I work with at Mastra. The lab's just where I practice.
You are the skill.
Try it
It's at jal-co/byolab (MIT), on v0.1.0 right now. Hit "Use this template", open it with your agent, and ask it what to do.
If you build one, show me what's in it :)