How to Get Started with Mitosis
Updated
Mitosis lets you write a component once in a JSX-like syntax and compile it to React, Vue, Svelte, Qwik, Angular, and other frameworks. The fastest way to start is the online Playground, where you can paste or edit a .jsx component and see the generated output for each target framework without installing anything. If you want Mitosis inside your own project, the official "Get Started" path is to install the Mitosis package and import from @builder.io/mitosis.
Try it in the Playground first
The Playground is the lowest-friction entry point. You write a single component using Mitosis's JSX dialect, and the tool shows you the equivalent source for the frameworks it supports.
A minimal component looks like this:
import { useState } from "@builder.io/mitosis";
export default function MyComponent(props) {
const [name, setName] = useState("Steve");
return (
<div>
<input
css={{ color: "red" }}
value={name}
onChange={(event) => setName(event.target.value)}
/>
Hello! I can run natively in React, Vue, Svelte, Qwik, and many more frameworks!
</div>
);
}
From this single input, Mitosis produces framework-native output. The same component becomes:
- Vue — a
<template>with arefand scoped<style> - Svelte — a
<script>block withbind:valueand a<style>block - Angular — a
@Componentwith an inline template andstylesarray - Qwik — a
component$usinguseStoreanduseStylesScoped$
The point of the example is the mapping, not the markup: state (useState), styling (css), and event handlers (onChange) each have a defined translation into every target framework.
What to notice in the compiled output
Reading the generated code teaches you the rules faster than any docs page, because each framework's version shows how Mitosis interprets your input.
| Mitosis input | Vue output | Svelte output | Angular output | Qwik output |
|---|---|---|---|---|
useState("Steve") |
ref("Steve") |
let name = "Steve" |
class property name = "Steve" |
useStore({ name: "Steve" }) |
css={{ color: "red" }} |
scoped <style> |
<style> block |
styles array |
useStylesScoped$ |
onChange={...} |
@change |
bind:value |
template binding | onChange$ |
Two practical takeaways:
- Write framework-agnostic logic. Anything you put in the component body should be expressible in all targets. If you reach for a React-only hook or a Vue-only directive, the compiler has nothing to map it to.
- Let Mitosis own the styling and events. Using
cssand standard handlers keeps the output consistent; hand-rolled DOM manipulation will not translate cleanly.
Move from Playground to a real project
Once the Playground output looks right, the official "Get Started" flow is the next step. The general shape of it:
- Install the Mitosis package so you can import
@builder.io/mitosisin your source files. - Write your components as
.jsx(or.lite.tsx) files using the Mitosis syntax shown above. - Run the Mitosis CLI/build step to emit the target framework code.
- Consume the generated output in your React, Vue, Svelte, Qwik, or Angular app.
The exact commands and configuration live in the official Get Started guide, which is the authoritative source for current setup instructions — check it rather than relying on a remembered command, since build tooling changes.
Common sticking points
- Framework-specific APIs don't port. If a component depends on something only React or only Vue provides, expect the compiled version to be incomplete or wrong. Keep shared components to the common subset.
- State and lifecycle are the hard part. Simple props and markup translate reliably; complex effects and refs are where cross-framework compilation gets fiddly. Prototype those in the Playground before committing.
- Verify each target, not just one. A component that compiles cleanly to React may still produce awkward Vue or Angular output. The Playground's side-by-side view exists precisely so you can check all targets at once.
When Mitosis is the right choice
Use Mitosis when you are building a multi-framework design system — a shared component library that has to ship to more than one framework — and you want a single source of truth instead of maintaining parallel implementations. The Builder.io description frames it exactly this way: "Write components once, run everywhere."
It is a weaker fit when you only target one framework, or when your components lean heavily on framework-specific features that have no cross-framework equivalent. In those cases the translation layer adds overhead without buying you portability.
Start in the Playground with the example above, confirm the generated output for the frameworks you actually need, then follow the official Get Started guide to wire Mitosis into your build.