A lightweight and flexible microfrontend framework for building scalable, independently deployable frontend applications.
Tuvix.js merges multiple frontend applications into a seamless, unified user experience - just like its name suggests.
🇬🇧 English · 🇹🇷 Türkçe · 🇪🇸 Español · 🇩🇪 Deutsch · 🇫🇷 Français · 🇯🇵 日本語 · 🇨🇳 中文 · 🇮🇹 Italiano · 🇧🇷 Português · 🇮🇳 हिंदी
- 🧩 Framework Agnostic - Use React, Vue, Svelte, Angular or Vanilla JS
- 📦 Independent Deployment - Deploy each micro app separately
- 🔗 Dynamic Module Loading - Load micro frontends on demand
- 🛣️ Built-in Routing - Seamless routing across micro apps
- 📡 Inter-App Communication - Event bus for cross-app messaging
- ⚡ Lightweight - Zero runtime dependencies, minimal core
- 🔄 Lifecycle Management - Mount, unmount, update hooks
- 🔒 Type-Safe - Full TypeScript support with strict types
Generate tuvix.js components from natural language using our built-in AI chatbot.
- Chat model: MiniMax M2.5 via OpenRouter (free API, no self-hosting required)
- Embed model: NVIDIA Nemotron Embed 1B via OpenRouter (RAG retrieval)
- Supports: React, Vue, Svelte, Angular
- Dataset: tuvix-component-dataset on HuggingFace
Try it: AI Generator on the documentation site
# All-in-one package
npm install tuvix.js
# Or install individual packages
npm install @tuvix.js/core @tuvix.js/routerimport { createOrchestrator } from 'tuvix.js';
const orchestrator = createOrchestrator({
router: {
mode: 'history',
routes: [
{ path: '/dashboard/*', app: 'dashboard' },
{ path: '/settings/*', app: 'settings' },
],
},
});
orchestrator.register({
name: 'dashboard',
entry: 'https://cdn.example.com/dashboard/main.js',
container: '#main-content',
activeWhen: '/dashboard/*',
});
orchestrator.register({
name: 'settings',
entry: 'https://cdn.example.com/settings/main.js',
container: '#main-content',
activeWhen: '/settings/*',
});
orchestrator.start();import { defineMicroApp } from 'tuvix.js';
let titleEl: HTMLHeadingElement | null = null;
export default defineMicroApp({
name: 'dashboard',
bootstrap() {
// One-time setup before first mount (e.g. preload data)
console.log('Dashboard bootstrapped');
},
mount({ container, props }) {
container.innerHTML = `<h1>Welcome, ${props?.user ?? 'Guest'}!</h1>`;
titleEl = container.querySelector('h1');
},
unmount({ container }) {
titleEl = null;
container.innerHTML = '';
},
// Triggered when the shell calls orchestrator.updateAppProps(name, props).
// Patch the live DOM in place — no remount, no flash.
update({ props }) {
if (titleEl) {
titleEl.textContent = `Welcome, ${props?.user ?? 'Guest'}!`;
}
},
});Pass new props to a mounted micro app without remounting:
// Push updated props from the shell — invokes the micro app's update() hook
await orchestrator.updateAppProps('dashboard', {
user: 'Yasin',
theme: 'dark',
});Props are merged with the original config props. If the app does not implement
update(), the new props are stored and applied on the next mount.
// Manually mount / unmount apps outside of route reconciliation
await orchestrator.mountApp('dashboard');
await orchestrator.unmountApp('dashboard');
// Inspect current state
orchestrator.getAppStatus('dashboard'); // 'mounted' | 'mounting' | 'error' | ...
orchestrator.getMountedApps(); // ['dashboard']
orchestrator.getRegisteredApps(); // ['dashboard', 'settings']
// Tear everything down (idempotent — safe to call multiple times)
await orchestrator.destroy();If you already use TanStack Router, Next.js App Router, or React Router, skip
config.router entirely and let your existing router drive Tuvix.js via
reconcile(path):
const orchestrator = createOrchestrator(); // no router config
orchestrator.register({
name: 'dashboard',
entry: '/dashboard.js',
container: '#main',
activeWhen: '/dashboard/*',
});
await orchestrator.start();
// After every navigation, tell tuvix.js what the current path is
tanstackRouter.subscribe('onLoad', () => {
orchestrator.reconcile(window.location.pathname);
});Defer expensive micro apps until their container scrolls into view:
orchestrator.register({
name: 'comments',
entry: '/comments.js',
container: '#comments-section',
mountWhenVisible: true, // mounts on first IntersectionObserver hit
});orchestrator.register({
name: 'reports',
entry: '/reports.js',
container: '#reports',
activeWhen: '/reports/*',
fallback: '<p class="error">Reports temporarily unavailable.</p>',
});const orchestrator = createOrchestrator({
router: { /* ... */ },
prefetch: {
strategy: 'idle', // 'immediate' | 'idle' | 'hover' | 'none' (default)
},
});| Strategy | When bundles are fetched |
|---|---|
immediate |
Right after start() |
idle |
During the next browser idle window (requestIdleCallback) |
hover |
After the user's first mouseover anywhere on the page |
none |
Never (default) — load on demand only |
import { createEventBus } from 'tuvix.js';
const bus = createEventBus();
// App A — emit event
bus.emit('user:login', { userId: 42, name: 'Ahmet' });
// App B — subscribe (returns an unsubscribe function)
const unsubscribe = bus.on('user:login', (data) => {
console.log(`${data.name} logged in!`);
});
// Fire once and auto-unsubscribe
bus.once('app:ready', () => console.log('ready'));
// Listen to every event for debugging
bus.onAny((event, data) => console.log('[bus]', event, data));
// Cleanup
unsubscribe();The orchestrator exposes its own bus via orchestrator.getEventBus() so all
registered apps share a single channel automatically.
import { createRouter } from 'tuvix.js';
const router = createRouter({
mode: 'history', // or 'hash'
base: '/', // optional base path
routes: [
{ path: '/dashboard/*', app: 'dashboard' },
{ path: '/users/:id', app: 'users' },
{ path: '/settings', app: 'settings', exact: true },
],
});
// Programmatic navigation
await router.push('/dashboard/overview');
await router.replace('/users/42');
router.back();
// Navigation guards (return false to cancel)
const off = router.beforeEach(async ({ from, to }) => {
if (to.startsWith('/admin') && !isAdmin()) return false;
});
// React to changes
router.onChange(({ from, to, toRoute }) => {
console.log(`navigated ${from} → ${to}`, toRoute?.params);
});
// Or use the orchestrator's built-in navigation helper
await orchestrator.navigateTo('/settings');┌─────────────────────────────────────────────┐
│ Tuvix.js Shell │
│ ┌─────────────────────────────────────────┐│
│ │ Orchestrator ││
│ │ ┌──────────┐ ┌──────────┐ ┌─────────┐ ││
│ │ │ Router │ │Event Bus │ │ Loader │ ││
│ │ └──────────┘ └──────────┘ └─────────┘ ││
│ └─────────────────────────────────────────┘│
│ │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ App A │ │ App B │ │ App C │ ... │
│ │(React)│ │ (Vue) │ │(Svelte│ │
│ └───────┘ └───────┘ └───────┘ │
└─────────────────────────────────────────────┘
| Package | Description |
|---|---|
tuvix.js |
All-in-one umbrella package |
@tuvix.js/core |
Core orchestrator with lifecycle management |
@tuvix.js/router |
URL-based micro app routing |
@tuvix.js/event-bus |
Inter-app communication event bus |
@tuvix.js/loader |
Dynamic module loader |
@tuvix.js/sandbox |
CSS/JS isolation (Shadow DOM + Proxy) |
@tuvix.js/react |
React 18+ bindings & hooks |
@tuvix.js/vue |
Vue 3 bindings & composables |
@tuvix.js/svelte |
Svelte 3-5 bindings |
@tuvix.js/angular |
Angular 15+ bindings |
create-tuvix-app |
CLI scaffolding tool |
@tuvix.js/devtools |
In-page debug panel |
@tuvix.js/server |
Server-side composition |
@tuvix.js/module-federation |
Webpack Module Federation integration |
tuvix.js/
├── packages/
│ ├── core/ # @tuvix.js/core
│ ├── router/ # @tuvix.js/router
│ ├── event-bus/ # @tuvix.js/event-bus
│ ├── loader/ # @tuvix.js/loader
│ ├── sandbox/ # @tuvix.js/sandbox
│ ├── react/ # @tuvix.js/react
│ ├── vue/ # @tuvix.js/vue
│ ├── svelte/ # @tuvix.js/svelte
│ ├── angular/ # @tuvix.js/angular
│ ├── cli/ # create-tuvix-app
│ ├── devtools/ # @tuvix.js/devtools
│ ├── server/ # @tuvix.js/server
│ ├── module-federation/ # @tuvix.js/module-federation
│ └── tuvix/ # tuvix.js (umbrella)
├── examples/
│ ├── with-angular/ # Angular 15+ example
│ ├── with-module-federation-react/ # Module Federation + React example
│ ├── with-multiple-frameworks/ # Multiple frameworks example
│ ├── with-react/ # React 18+ example
│ ├── with-react-devtools/ # React + DevTools example
│ ├── with-react-event-bus/ # React + Event Bus example
│ ├── with-react-router/ # React + Router example
│ ├── with-react-sandbox/ # React + Sandbox example
│ ├── with-ssr-react/ # SSR + React example
│ ├── with-ssr-vanilla/ # SSR + Vanilla JS example
│ ├── with-svelte/ # Svelte 5 example
│ ├── with-vanilla/ # Vanilla JS example
│ └── with-vue/ # Vue 3 example
├── website/ # Documentation site (VitePress, 10 languages)
├── .github/ # CI/CD workflows
├── package.json # Root workspace config
├── pnpm-workspace.yaml
├── tsconfig.base.json
└── vitest.config.ts
- Core orchestrator
- Lifecycle management
- Dynamic module loading
- Event bus
- URL routing with history/hash modes
- CSS/JS sandbox isolation
- CLI scaffolding tool (
npx create-tuvix-app) - DevTools browser extension
- Server-side composition (
@tuvix.js/server) - Module federation support
- Framework bindings (React, Vue, Svelte, Angular)
- i18n documentation (10 languages)
- Example tests & CI coverage for examples
- Hot module reload across micro apps
- Shared state management adapter (Zustand / Pinia adapter layer)
- Plugin system & middleware API
- Native ESM / importmap support
- Intersection Observer–based viewport mounting - lazy-mount apps only when their container scrolls into view, reducing initial JS execution cost
- BigPipe-style streaming SSR - send the shell HTML immediately over chunked transfer encoding, then stream each micro-app fragment as it resolves; dramatically reduces Time To First Byte compared to the current synchronous
composeHTMLapproach - Pre-compiled shell templates - compile the slot-injection template once at server startup rather than per request
- Critical CSS extraction - inline above-the-fold styles in SSR responses for faster Largest Contentful Paint
- Edge/CDN-aware server composition with stale-while-revalidate fragment caching
- Fail-safe fallback fragments - declarative per-app fallback HTML shown automatically when a micro-app fails to load or exceeds its timeout; keeps the page usable even when one service is down
- Fragment A/B testing - register multiple versions of a micro-app and select at runtime via cookie matcher or custom predicate, enabling gradual rollouts without redeploying the shell
- Prometheus-compatible metrics endpoint (
/metrics) from@tuvix.js/server- track mount/unmount counts, load durations, and error rates per app - Visual dependency graph in DevTools
- VS Code extension for DevTools integration
- Testing utilities & mock orchestrator
- Storybook integration for micro app isolation
- Preloading & prefetching strategies (already partially available via
prefetch.strategyconfig)
Ready-to-run examples for each supported framework are available in the examples/ directory:
| Example | Framework | Path |
|---|---|---|
| Angular Example | Angular 15+ | examples/with-angular/ |
| Module Federation + React Example | React 18+ | examples/with-module-federation-react/ |
| Multiple Frameworks Example | Mixed | examples/with-multiple-frameworks/ |
| React Example | React 18+ | examples/with-react/ |
| React + DevTools Example | React 18+ | examples/with-react-devtools/ |
| React + Event Bus Example | React 18+ | examples/with-react-event-bus/ |
| React + Router Example | React 18+ | examples/with-react-router/ |
| React + Sandbox Example | React 18+ | examples/with-react-sandbox/ |
| SSR + React Example | React 18+ | examples/with-ssr-react/ |
| SSR + Vanilla JS Example | No framework | examples/with-ssr-vanilla/ |
| Svelte Example | Svelte 5 | examples/with-svelte/ |
| Vanilla JS Example | No framework | examples/with-vanilla/ |
| Vue Example | Vue 3 | examples/with-vue/ |
Each example demonstrates:
- A shell (host) application that boots the orchestrator
- Two micro frontend apps registered and loaded dynamically
- Inter-app communication via the event bus
Contributions are welcome! Please read the Contributing Guide before submitting a PR.
# Clone the repo
git clone https://github.com/yasinatesim/tuvix.js.git
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm testCopyright © 2026 - MIT License. See LICENSE for more information.
This README was generated by markdown-manager 🥲