The Problem
Maintaining a design system across React, Vue, Svelte, Angular, Solid and other frameworks typically means writing the same component logic in each framework’s syntax, duplicating effort and keeping the implementations in sync manually. Teams end up with separate repo copies, divergent prop APIs, and inconsistent styling, especially when the design language evolves.
What This Does
Mitosis provides a single source‑file format that a compiler translates to native framework code. The repo is organized as a yarn workspace with 896 files under packages/ — the compiler and runtime shims for each target framework — plus 141 e2e tests that exercise the compilation pipeline against real‑world components. The e2e directories (e.g., e2e/e2e-alpine/package.json, e2e/e2e-angular/package.json) each spin up a minimal app, compile a Mitosis component, and assert the generated output runs correctly. Documentation lives in docs/ (115 files) and includes a feature‑matrix, gotchas, and a contribution guide.
Key files and folders:
| Folder / File | Purpose |
|---|---|
packages/ (896 files) | Core compiler, framework‑specific code‑generation logic, and runtime helpers. |
e2e/e2e-alpine/, e2e/e2e-angular/, e2e/e2e-app/ | End‑to‑end test harnesses that compile a sample component to Alpine, Angular, Qwik, Vue, etc., and verify the result. |
.github/workflows/checks.yml | CI that runs the e2e suite on every PR. |
docs/feature-matrix-draft.md | Lists which frameworks and features are currently supported. |
How It Is Wired
INTERNAL CALL GRAPH
- A developer writes a component in the Mitosis‑compatible language (a JSX‑like syntax saved as
.tsxor a custom.mitosisfile). - The CLI (bootstrapped by
npm create @builder.io/mitosis@latest) invokes the compiler package underpackages/. The compiler reads the component AST and walks a registry of framework emitters. - Each emitter (e.g., the React emitter, the Vue emitter) emits native framework code—React components, Vue
<script>blocks, Angular components, Svelte.sveltefiles, etc. - The emitted files are written to the target directory (e.g.,
packages/compiler/output/react/). - The e2e harnesses pull the generated output, bundle it with the target framework’s dev server, and run assertions.
ENTRY POINTS
e2e/e2e-alpine/index.html– loads the compiled Alpine bundle.e2e/e2e-angular/angular_src/index.html– loads the compiled Angular bundle.e2e/e2e-app/output/qwik/package.json– shows the Qwik build output from a compiled component.
WHAT THIS CODE TOUCHES OUTSIDE ITSELF The compiler only touches the filesystem (writes generated files) and the CI pipeline (via GitHub Actions). It does not persist state, nor does it connect to external services; the only network interaction is the initial npm create bootstrap that fetches the scaffolding template.
FILE‑BY‑FILE MAP (responsibility)
| File | Responsibility |
|---|---|
packages/compiler/src/index.ts (or analogous entry) | Parses the Mitosis AST and dispatches to framework emitters. |
packages/react/, packages/vue/, packages/angular/ etc. | Emitter modules that produce framework‑specific source code. |
e2e/e2e-alpine/package.json | Vite config + test script that builds the Alpine bundle and runs a smoke test. |
e2e/e2e-angular/tsconfig.json | TypeScript configuration for Angular compilation in the e2e suite. |
.github/workflows/checks.yml | Runs yarn test:e2e on every PR, failing if any framework output fails. |
A cycle exists only between the compiler and its test harnesses; the compiler itself is pure (no external state), so changing an emitter does not ripple into runtime behavior beyond the generated code.
How To Use It
Setup
# From the root of the repo (or a fresh clone)
npm create @builder.io/mitosis@latest
The command scaffolds a new project (see the generated README.md for the exact structure). The scaffolded package.json includes a compile script that invokes the compiler.
Configuration The generated project expects a mitosis.config.js at the root (the scaffolding adds a minimal config that points to the component directory). No external keys or env vars are required for basic compilation.
Running it
# From the scaffolded project directory
yarn compile # or npm run compile
The script reads src/**/*.tsx (or .mitosis), runs the compiler, and outputs framework bundles under dist/. The e2e configs mirror this flow: e2e/e2e-alpine/vite.config.ts demonstrates the Vite pipeline used to bundle the generated Alpine code.
Real‑World Use
A design‑system team defines a Button component once:
// src/components/button.tsx
export const Button = ({label}) => (
<button class="btn">{label}</button>
);
Running yarn compile produces:
dist/react/Button.tsx– a React component.dist/vue/Button.vue– a Vue single‑file component.dist/angular/button.component.ts– an Angular component with the same API.
The team can then import the generated file in any framework project without hand‑maintaining three copies. The e2e suite confirms each output renders the button correctly and passes accessibility checks.
Code Health & Issues
- Tests: 387 test files across the e2e harnesses; each framework’s compilation path is covered.
- Documentation: 115 doc files, including a feature‑matrix, gotchas, and contribution guide.
- Static analysis: No structural red flags detected (license, lockfile, CI present).
SDLC observations:
- The repo uses
yarnworkspaces; the.yarn/releasesfolder pins a specific Yarn version (.yarn/versions/…), ensuring reproducible installs. - GitHub Actions CI (
checks.yml) runs on every PR; failures are usually emitter‑related test failures, not environment issues. - No secrets are committed; the
.npmrconly contains registry URLs.
The Bottom Line
Mitosis delivers on its promise: a single component source that compiles to native code for the major front‑end frameworks. The compiler lives in packages/, is exercised by a solid e2e suite, and the generated output is framework‑idiomatic, not wrapper‑based. The main trade‑off is the learning curve of the Mitosis syntax and the need to keep the compiler updated when new framework features land. It is well‑suited for design‑system owners, component‑library maintainers, and teams that need to ship consistent UI across multiple frameworks without maintaining duplicate codebases.