Guidelines
The taste, not the mechanics.
This page is what the repository asks of a submission and why. CONTRIBUTING.md stays the mechanical how-to — setup, the file layout, the verify gate commands. Read this one first; it's shorter and it's the part that actually decides whether something gets merged.
One interaction
The bar for a new component is an interaction that does not already exist here — not a component that merely works. A button styled differently from an existing button is not a new interaction. A button that reveals a hold-to-confirm affordance, or that reacts to the cursor's position rather than its click, is. If two submissions would demonstrate the same behavior, only the clearer one belongs.
Both themes are non-negotiable
Every component ships in dark and light, and both are graded, not just the one your terminal defaults to. A component can read perfectly in dark and fall apart in light — a gradient that inverts, ink that vanishes into the background, a shadow that becomes a smear. The gate only fails a component whose two themes render byte-identical, so a light theme that is merely wrong sails straight through it. Look at both yourself.
The card matters as much as the preview
The homepage renders your component live, scaled down into a card roughly 660px wide. A demo that reads fine at full size can arrive in the grid as a speck of interface adrift in empty background, or with the interesting part outside the frame. A submission is judged on what a stranger sees in that card before they ever click through to the full page — if the card doesn't say what the component does, the component isn't done yet.
The token rule
Color comes from the CSS custom properties already in scope — --background, --foreground, --muted, --border, and --accent— never a hardcoded hex, in markup or in canvas/SVG draw code. This broke the light theme across the whole registry once already. A component that derives ink for a canvas reads it with getComputedStyle at mount and on theme change, rather than baking a color literal in.
What gets rejected
A person reads every submission; the automated gate is the floor, not the bar. It hard-fails on:
- A console error on either theme, at any state.
- A blank render — nothing painted where the component should be.
- Hover that looks byte-identical to resting, or keyboard focus that looks byte-identical to unfocused. An interaction that doesn't visibly interact isn't one.
- Dark and light rendered as the same bytes — a component that ignored the theme rather than one that happens to look similar.
- An interactive control with no accessible name, a role of switch/checkbox/radio with no aria-checked, or a visible dialog with no accessible name.
- Controls that Tab cannot reach.
- Hardcoded hex in markup or in canvas/SVG draw code, instead of the CSS custom properties already in scope.
License and sign-off
A merged submission is contributed under the repository's MIT license — you keep authorship, the project keeps the right to distribute it under those terms. Every pull request certifies its own origin with a Developer Certificate of Origin: a checkbox and a Signed-off-by line in the commit, confirming you have the right to submit the code under that license. No sign-off, no merge.
Contributor credit and privacy
Nothing you save, and nothing you write on your profile, is visible to anyone unless you publish it. Publishing is per collection, and it is off until you turn it on.
Contributing a component to the repository is different: it is public git history under the GitHub identity you opened the pull request with. It is not covered by the privacy setting above, it is not something this site stores about you, and it survives deleting your account.
Credit for a contribution links to that contributor's profile only when one exists and is public. Otherwise it renders as their plain GitHub login, with no link — the same degradation a deleted account takes.