SKILL.md
React Micro-Frontend Patterns
The Pattern
Problem: You have multiple independently-built UI bundles that must share React at runtime, a form system driven by server-side schemas that change dynamically, and state that needs to persist in the browser and sync across tabs.
Approach: Import maps with Vite's rollupOptions.external for shared React, a useFrecency hook with exponential decay scoring, schema-to-React rendering with action-triggered schema refinement, and Zustand stores with localStorage sync.
Pattern proven in production across multiple React frontends and web services.
Key Design Decisions
1. Import map + rollupOptions.external for shared React
When multiple independently-built bundles run on the same page, each gets its own copy of React. This causes the "dual React instance" bug: hooks break because the React instance that rendered the component is different from the one providing useState.
The fix: externalize React in every bundle's Vite config and provide it via an import map in the HTML:
<!-- index.html -->
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/[email protected]",
"react-dom": "https://esm.sh/[email protected]",
"react-dom/client": "https://esm.sh/[email protected]/client",
"react/jsx-runtime": "https://esm.sh/[email protected]/jsx-runtime"
}
}
</script>
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime'],
},
},
})
2. The Vite dev-mode problem
Vite's dev server ignores browser import maps — it pre-bundles CJS modules and serves them from /.vite/deps/. This means dynamically-loaded bundles that use bare import React from 'react' will resolve via the import map to a different React instance than the host app.
Solutions: Use @vitejs/plugin-react with careful configuration, or write a custom Vite plugin that serves shim modules redirecting bare specifiers to Vite's pre-bundled paths during dev. This is inherently complex — consult your Vite config documentation for the specifics of your setup.
