Adding a second framework to a component library is mostly not a framework problem. The rendering layer is the visible part and the small part; what decides whether the result is one library with two targets or two libraries wearing the same logo is everything underneath it: the tokens, the names, the variant matrix, the behaviour contracts. Orvain 1.4 will ship Vue components alongside React, with forty new blocks, and this is a preview of it while it is being built. Most of the work that decides whether it succeeds happens in the layer neither framework owns.
What first-class support has to mean
A second target is only worth having if it is genuinely the same system. Same prop names, same variant values, same token names, same keyboard behaviour, same accessibility contract. Anything less produces the outcome every multi-framework library has to work to avoid, where the second implementation is a lagging subset and every piece of documentation quietly means the first one.
The test we hold it to is that a screen described in the design kit should be buildable in either target using the same vocabulary, and that a conversation about a component should not have to say which framework it is about until somebody actually writes code.
One token layer, two renderers
What makes this tractable is that the styling does not live in the framework. Tokens resolve through CSS custom properties, which belong to the browser rather than to React or Vue, so the entire question of what a component looks like: colour, radius, spacing, type, and how all of those change under a white-label theme: is answered identically on both sides without either implementation knowing the other exists.
What genuinely differs is narrower than it first appears: how children are passed and named, how reactive state is declared, how events are surfaced, and how each framework handles server rendering. Those are real differences and each one costs a real implementation. They are also differences in expression, not in contract, which is why the contract is the thing that gets written down first.
Server rendering is where the two diverge most, and where a shared contract is easiest to break by accident. Both frameworks will render a component to markup on the server and reconcile it in the browser afterwards, but what each one treats as a mismatch, and how loudly it says so, differs enough that a component careless with non-deterministic values: a generated identifier, a formatted date, anything read from the browser: will fail on one side long before it fails on the other.
Forty blocks, built from components you already have
A block is a composition, not a new primitive. The forty coming in 1.4 are assembled from the same forty-five components and the same token set as everything else in the library, which is what will make them useful the moment they land in a project: a pasted block picks up your theme because it never held a value of its own. They are already among the 212 blocks in the gallery on this site, designed and drawn live; 1.4 is the release that ships their code.
The reason blocks earn their place is that they encode the decisions a screenshot never shows. What the table does with no rows. What the form does while it is submitting. What order the keyboard walks through a filter bar. Those are the parts of a composition that take an afternoon each and are skipped under pressure, and having them already made is most of the value of a block library.
Blocks are also the part of the library you are meant to take apart. Copied code is yours to keep, so a block is a starting composition rather than a component with a supported surface, and cutting one in half to use the top of it is an ordinary thing to do rather than a misuse of the library.
Parity is the ongoing cost
Two targets means every future component is two implementations against one contract, and the discipline that keeps that from decaying is to change the contract first and both implementations second. A prop that appears on one side before it has been agreed for both is the beginning of the lagging subset, and it is much easier to refuse than to unwind.
It shows up in the tooling too. The MCP server is being built to describe one API, so an assistant asking what a component accepts gets an answer that is true regardless of which target the project is using, and the Figma kit keeps mirroring one vocabulary rather than growing a second dialect.
What exists now, and what 1.4 adds
What exists today is the Figma library and the 212 blocks drawn live on this site. What 1.4 adds is the code: forty-five strict-typed components for React and Vue, one white-label config that themes all of it, and one MCP endpoint that describes the whole surface to whatever assistant you point at it. The number worth watching is not the length of that list. It is whether every item on it still says the same thing as every other item, which is the harder property to keep and the only one that makes a release like this worth shipping.
The Orvain UI team
Writing about design systems and the tools that ship them.




