corvu is a set of unstyled SolidJS UI primitives
🐦⬛ Unstyled, accessible and customizable UI primitives for SolidJS
At a glance
- What is it?
- corvu is a collection of open source UI primitives for SolidJS that ship without styling, with accessibility behaviour, SSR support and a monorepo published per component under the @corvu scope. The trade is that you own every pixel, which is a feature for a design system and a burden for a quick prototype.
- Who is it for?
- corvu suits a team building a SolidJS design system that wants accessible behaviour such as focus trapping, dismissal and keyboard handling without adopting somebody else's visual language, since each primitive is published as its own package and you style it yourself.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 60 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the collection covers, and what it does not
corvu is a collection of open source UI primitives for SolidJS, and the README lists the offering in six short claims: unstyled, accessible primitives, high customizability, delightful developer experience, good documentation and SSR support.
The primitives that are documented are nine in total. There is an Accordion, a Calendar, a Dialog, a Disclosure, a Drawer, an OTP Field, a Popover, a Resizable, also labelled Resizable/Splitter, and a Tooltip.
That number is the first thing to weigh, and it is the reason corvu is best understood as a set of building blocks rather than a component library. A product interface will need a select, a combobox, a menu, a tabs component, a switch, a checkbox, a radio group, a slider, a toast. None of those appear in the documented list. The releases published under the @corvu scope reinforce the picture, with recent tags for @corvu/resizable at 0.2.5 and @corvu/unocss at 0.1.3, and a separate solid-prevent-scroll package at 0.1.11 that is not scoped to @corvu at all.
So the honest framing is: corvu solves the hard, fiddly primitives well, and leaves the ordinary ones to you or to another library.
Unstyled means you own the behaviour and the look
The unstyled claim is the defining design decision, and it is worth being precise about what it implies in both directions.
On the behaviour side, the accessibility work is already done. A Dialog primitive has to trap focus, restore it on close, handle the escape key, mark the rest of the page as inert to assistive technology, and manage a labelled relationship between the trigger and the dialog. A Popover has to position itself, respond to dismissal, and restore focus. Doing that correctly in every application is exactly the kind of repetitive work a primitive library exists to remove, and corvu does it.
On the look side, nothing is provided. There is no default theme, no opinionated spacing scale, no button styling, no colour tokens. You write the CSS. That is the right choice when you are building a design system with its own visual language, because a component library's defaults are always wrong for you and always present as a layer to override. It is the wrong choice for a weekend prototype, where the defaults are exactly what you wanted.
The customizability claim is the other half of this, and the high customizability and delightful developer experience claims are the README's own words rather than something the documentation excerpt here demonstrates. The documentation site is where you would check how much of the internals are exposed.
The monorepo and how the packages are published
The repository is a pnpm and turbo monorepo, and the layout tells you how the project is built and released.
The root package.json is named @corvu/monorepo and is private, with a pnpm-lock.yaml, a pnpm-workspace.yaml, a turbo.json and a packages directory. The workspace globs are the pnpm equivalent of lerna or nx, and turbo runs the tasks across the workspace.
The scripts show the shape of the developer loop. build runs turbo run build, and ci:publish runs pnpm build followed by pnpm publish -r --access public, which is what publishes the individual packages. lint runs turbo run lint, and there are dev:corvu and dev:web scripts that run turbo watch dev filtered to @corvu/dev and @corvu/web, matching the dev and web directories at the repository root. clean removes the turbo cache and node_modules.
Releases are automated with release-please, at version 17.11.0 as a dev dependency, and the repository carries a .release-please-manifest.json and a release-please-config.json. That is what produces the per-package tags, and it explains why the recent releases are named after packages rather than the repository: solid-prevent-scroll: v0.1.11 dated 2026-07-31, @corvu/resizable: v0.2.5 dated 2025-05-04, and @corvu/unocss: v0.1.3 dated 2025-04-08.
The consequence for a user is that the packages are versioned independently, and their release dates are weeks or months apart. A dependency on @corvu/dialog and one on @corvu/resizable will not be at the same point in their release cycles.
The Unocss package and the wider tooling
The @corvu/unocss package is the one release that tells you something about how the primitives expect to be styled, and it is worth a second look because it is not a primitive at all.
Unocss is an atomic CSS engine, and shipping a @corvu/unocss package means corvu is providing preset-style integration for it rather than only a set of headless components. That fits the unstyled positioning: the primitives give you behaviour, and this package helps you express that behaviour in a utility-first stylesheet without hand-writing every rule.
The package name also tells you that the design is not tied to one styling solution. Shipping an Unocss integration makes a deliberate point: the components are not coupled to one styling approach, and you can style them however your project already does.
Two other release signals are worth noting. The solid-prevent-scroll package is scoped differently, as solid-prevent-scroll rather than @corvu/solid-prevent-scroll, which suggests it is maintained as a separate utility rather than as part of the main collection, and it is the most recently released of the three, tagged 0.1.11 on 2026-07-31. And the whole set is still at low version numbers, with the newest @corvu package tag at 0.2.5, which is a signal about API stability rather than about quality.
Where to get it, and what the README does not say
The README does not contain an installation section, and that is a real gap rather than an oversight in the documentation site, which is where the README sends you for the primitive by primitive guides.
What the repository does tell you is the shape of the distribution. The packages live on npm under the @corvu scope, with names matching the primitives, so the accordion package is @corvu/accordion, the calendar is @corvu/calendar, the dialog is @corvu/dialog, the disclosure is @corvu/disclosure, the drawer is @corvu/drawer, the OTP field is @corvu/otp-field, the popover is @corvu/popover, the resizable is @corvu/resizable and the tooltip is @corvu/tooltip. The README's download badge lists exactly those nine names alongside solid-prevent-scroll, which confirms the naming scheme rather than inventing it.
The npm download badge is also a combined endpoint, which tells you the project tracks usage across all of its packages together rather than one at a time.
The package manager for the repository itself is pinned in the root package.json, with packageManager set to [email protected], and the packages directory is a pnpm workspace with a pnpm-lock.yaml. So if you are working on corvu itself, pnpm is the tool, and the turbo pipeline handles the builds.
What you will not find in the README is a note on which SolidJS versions are supported, a peer dependency list, or a compatibility matrix. Those live in the individual package manifests and in the documentation site, and the fact that the packages are released independently is a good reason to check the version of each one you install rather than assuming they move together.
SSR support and the SolidJS assumption
The README lists SSR Support among the six things the collection offers, and for a SolidJS library that is a real constraint rather than a checkbox.
SolidJS renders on the client by default, and components that touch the document during setup will break under server rendering. A Dialog that measures its trigger on mount, a Popover that computes a position from getBoundingClientRect, a Calendar that reads the current date, and a Drawer that locks body scroll all have to be written so the server pass produces something harmless and the client pass produces the interactive result. The presence of an SSR support claim means the primitives were built with that split in mind.
The scroll locking case is instructive. Preventing background scroll while a modal is open is a well known source of layout shift, and the fact that a dedicated solid-prevent-scroll package exists as the most recent release suggests the primitives build on a tested solution rather than each implementing it.
SolidJS itself is the other assumption. This is not a React library with a Solid adapter; the primitives are written against Solid's fine-grained reactivity, its context model and its JSX. The topics list names solid and solidjs, and the headless primitives topic is the giveaway that these are behaviour-only components in the style of the headless UI movement.
The author of the project is Jasmin Noetzli, working on the GiyoMoon GitHub account, and the licence is MIT. The website is corvu.dev, and the README also points at a GitHub discussions board and the SolidJS Discord.
Where corvu fits against the alternatives
The comparison worth making is with the other options in the SolidJS world, and the difference is mostly about where the work goes.
A styled component library gives you finished components and a look you did not choose. A headless library gives you behaviour and requires you to write the CSS. corvu sits in the second camp, and its documentation is where the argument would be won or lost, since the accessibility claims and the developer experience claims can only be checked by using the components.
Within the headless category, the differences show up in coverage and in how much of the internals are exposed. A primitive that renders only a trigger and a content panel gives you total control over the markup but makes you handle positioning, the arrow and the transition. A primitive that renders a positioned wrapper gives you a working component out of the box and leaves you with a wrapper element to style around. The README's high customizability claim points to the first approach, and the per-primitive documentation is where you would confirm it.
There is also the option of not using a primitive library at all, and for SolidJS that is more viable than in React. Solid's reactivity makes a lot of interactive components short enough to write directly, and a team with strong opinions about markup may prefer that. The trade is that the accessibility details still have to be written, and they are the details that are hard to retrofit later.
The practical difference between corvu and a general purpose headless set is the SolidJS specificity. Porting an existing React headless library is a nontrivial exercise because it depends on React's render cycle and hooks, so a native Solid implementation avoids a class of problem entirely.
Editorial conclusion
corvu suits a team building a SolidJS design system that wants accessible behaviour such as focus trapping, dismissal and keyboard handling without adopting somebody else's visual language, since each primitive is published as its own package and you style it yourself. It is the wrong choice for a quick prototype, because unstyled means you write the CSS for every primitive you use, and it is the wrong choice if you want a complete component set, since the documented list covers nine primitives rather than the dozens a product UI tends to need. Before adopting it, read the documentation for the specific primitive at corvu.dev/docs/primitives, and check the release history, because the packages are versioned independently and their tags land weeks apart.
Frequently asked questions
What primitives does corvu provide?
The documented set is nine: Accordion, Calendar, Dialog, Disclosure, Drawer, OTP Field, Popover, Resizable, also called Resizable/Splitter, and Tooltip. The README describes corvu as a collection of open source UI primitives for SolidJS rather than a complete component library.
Is corvu styled or headless?
It is unstyled. The README lists unstyled as its first offering, so the accessibility behaviour is provided but the visual appearance is left to you, which is the right choice for a design system and extra work for a quick prototype.
How is corvu released?
Each primitive is published as its own npm package under the @corvu scope, with automated releases through release-please, which is configured with a .release-please-manifest.json and a release-please-config.json. Recent tags include @corvu/resizable at 0.2.5, @corvu/unocss at 0.1.3 and solid-prevent-scroll at 0.1.11.
Does corvu work with server side rendering?
Yes. SSR Support is one of the six things the README says corvu offers, and the primitives are written for SolidJS, which renders on the client by default, so the components are built to produce a harmless server pass and an interactive client pass.
What licence is corvu under?
MIT. The root package.json records the license as MIT with the homepage https://corvu.dev, and the README carries a licence badge pointing at the LICENSE file in the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/corvudev-corvu)Was this useful?