English | Chinese
A React component toolchain for AI agent platforms and agent containers. It gives third-party developers a local-like experience while the host container hot-reloads components in real time.
Quick start:
npm create dev-to- create your first project in ~30 seconds.
As AI agent platforms grow, enterprises often need an agent container that allows:
- Internal teams to build their own agent cards.
- External developers to ship plugin components.
- Multi-team collaboration with independent ownership and deployment.
Common pain points with traditional integration:
- Host environment is a black box: components must be deployed into the container to debug.
- Slow feedback loops: rebuild and redeploy for every change.
- Production debugging is hard: limited visibility into runtime behavior.
- Asset path issues: images and fonts 404 in the container.
- Runtime conflicts: multiple React instances lead to hooks errors.
dev-to solves this by:
- Keeping container details hidden while keeping component logic transparent.
- Enabling cross-environment HMR with Vite Dev Server.
- Standardizing discovery and runtime protocols between host and components.
- Cross-environment HMR between Vite and the host container.
- Local-like debugging in production (opt-in).
- Standard discovery endpoint and bridge contracts.
- Built-in debug panel and UMD packaging.
- Shared React runtime to avoid multi-instance conflicts.
| Solution | Core focus | Maturity |
|---|---|---|
| Module Federation | Build-time module sharing (Webpack/Vite native) | Production-ready |
| qiankun | Runtime application isolation (micro-frontend) | Production-ready |
| micro-app | WebComponent-like micro-frontend | Production-ready |
| single-spa | Micro-frontend routing orchestration | Production-ready |
| dev-to | Cross-environment component HMR | Early stage |
| Feature | Module Federation | qiankun | micro-app | single-spa | dev-to |
|---|---|---|---|---|---|
| Runtime module sharing | Native | Config required | Config required | Config required | Native |
| Cross-app HMR | Partial | No | No | No | Core feature |
| JS sandbox | No | Proxy sandbox | iframe/Proxy | No | No |
| CSS isolation | No | Shadow DOM/Scoped | Shadow DOM | No | CSS Modules |
| Route management | No | Yes | Yes | Core feature | No |
| Preloading | Yes | Yes | Yes | Yes | No |
| Multi-framework | Yes | Yes | Yes | Yes | React only |
| TypeScript type sharing | Plugin required | No | No | No | Native |
| Metric | Module Federation | qiankun | dev-to |
|---|---|---|---|
| Initial setup time | 30-60 min | 15-30 min | ~5 min |
| Cross-app HMR | Host refresh needed | Full refresh needed | Real-time hot reload |
| Debug tools | None built-in | None built-in | Built-in debug panel |
| Type hints | Requires @mf-types | None | Native support |
Need cross-environment HMR during development?
├── Yes → dev-to (only native solution currently)
└── No ↓
Need JS/CSS sandbox isolation?
├── Yes → qiankun / micro-app
└── No ↓
Need module-level sharing (not app-level)?
├── Yes → Module Federation
└── No ↓
Need multi-framework support?
├── Yes → single-spa + framework adapters
└── No → Evaluate specific requirements
| Solution | Best for |
|---|---|
| Module Federation | Large-scale component/module sharing across apps |
| qiankun | Enterprise micro-frontend with team isolation |
| micro-app | Quick integration with legacy systems |
| single-spa | Multi-framework progressive migration |
| dev-to | AI agent plugin platforms, best-in-class DX for component hot-reload |
dev-to's unique value: It is currently the only solution focused on "real-time HMR inside a host container". If your core pain point is "third-party developers code locally while the host environment previews in real-time", dev-to is the most direct choice. However, if you need sandbox isolation, route management, or other enterprise features, consider qiankun or Module Federation.
| Package | Version | Description |
|---|---|---|
| create-dev-to | Scaffold tool to create dev-to projects (multi-framework). | |
| @dev-to/react-plugin | Vite-side plugin to expose bridge endpoints. | |
| @dev-to/react-loader | Host-side loader that mounts remote React components. | |
| @dev-to/react-shared | Shared protocol, constants, and types. | |
| @dev-to/react-template | - | Example component provider (private). |
| @dev-to/react-playground | - | Example host app (private). |
graph TB
subgraph Container["AI Agent container (platform / enterprise)"]
subgraph Runtime["Container runtime (React application)"]
R["Provide shared UI framework<br/>Manage agent lifecycle<br/>Handle routing and interactions"]
end
subgraph Loader["@dev-to/react-loader (component loading layer)"]
L["Load remote components (dev: Vite Dev Server)<br/>Load remote components (prod: CDN / static hosting)<br/>Support dev/prod switch"]
end
end
Container -->|HTTP/S| DevA
Container -->|HTTP/S| DevB
Container -->|HTTP/S| DevC
subgraph DevA["Team A (local dev)"]
A["Vite Dev localhost:5173<br/><br/>@dev-to/react-plugin<br/><br/>Components: support card, order card"]
end
subgraph DevB["Team B (local dev)"]
B["Vite Dev localhost:5174<br/><br/>@dev-to/react-plugin<br/><br/>Components: report card, approval card"]
end
subgraph DevC["Third-party developer (local dev)"]
C["Vite Dev localhost:5175<br/><br/>@dev-to/react-plugin<br/><br/>Components: weather plugin, calendar plugin"]
end
@dev-to/react-shared (base protocol)
+-- @dev-to/react-plugin (Vite side)
| +-- @dev-to/react-template (example)
+-- @dev-to/react-loader (host side)
+-- @dev-to/react-playground (example)
create-dev-to (standalone scaffold)
Component developer:
- Create a component project with the scaffold.
- Develop in Vite Dev Server (for example, localhost:5173).
- Share the origin and component names with the container team.
- The container loads the component via @dev-to/react-loader.
- Code changes hot-reload inside the container.
- Build UMD bundles and deploy to CDN for production.
Container team:
- Integrate @dev-to/react-loader.
- Configure which components to load.
- Load local Vite origins in dev.
- Load CDN-hosted UMD bundles in production.
- Onboard new components without touching container code.
Unified discovery endpoint: /__dev_to__/discovery.json (v2+)
{
framework: {
type: 'react',
version: '18.2.0'
},
server: {
host: 'localhost',
port: 5173,
protocol: 'http',
origins: ['http://localhost:5173', 'http://127.0.0.1:5173', 'http://192.168.x.x:5173']
},
endpoints: {
discovery: '/__dev_to__/discovery.json',
contract: '/__dev_to__/react/contract.js',
init: '/__dev_to__/react/init.js',
runtime: '/__dev_to__/react/runtime.js',
debug: {
html: '/__dev_to__/debug.html',
json: '/__dev_to__/debug.json'
},
loader: {
base: '/__dev_to__/react/loader',
umd: '/__dev_to__/react/loader.js'
}
},
components: {
'MyCard': {
name: 'MyCard',
entry: 'src/components/MyCard.tsx',
framework: 'react'
}
},
events: {
fullReload: 'dev_to:react:full-reload',
hmrUpdate: 'dev_to:react:hmr-update'
},
protocol: {
version: '2.0.0',
apiLevel: 1
}
}Legacy bridge contract (for compatibility): /__dev_to__/react/contract.js
{
paths: {
contract: '/__dev_to__/react/contract.js',
initClient: '/__dev_to__/react/init.js',
reactRuntime: '/__dev_to__/react/runtime.js'
},
events: {
fullReload: 'dev_to:react:full-reload',
hmrUpdate: 'dev_to:react:hmr-update'
},
dev: {
componentMap: {
'MyCard': 'src/components/MyCard.tsx'
}
}
}npm create dev-to
# or pnpm create dev-to
# or yarn create dev-to
# or bun create dev-toScaffold highlights:
- Choose framework (React supported now; Vue/Svelte/Solid planned).
- Choose package manager (pnpm/npm/yarn/bun).
- Choose React template (TypeScript/JavaScript, SWC support).
- Optional Rolldown experiments.
npm install -D @dev-to/react-pluginConfigure Vite:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { devToReactPlugin } from '@dev-to/react-plugin'
export default defineConfig({
server: {
port: 5173,
cors: true,
},
plugins: [
react(),
devToReactPlugin({
MyCard: 'src/components/MyCard.tsx',
MyHeader: 'src/components/Header.tsx',
}),
],
})npm install @dev-to/react-loaderUse the loader in the host app:
import { ReactLoader } from '@dev-to/react-loader'
function App() {
return (
<div>
<h1>Host application</h1>
<ReactLoader
origin="http://localhost:5173"
name="MyCard"
componentProps={{ title: 'Title', count: 42 }}
/>
</div>
)
}# Terminal 1
cd component-provider
npm run dev
# Terminal 2
cd host-app
npm run dev// A) wildcard mode (debug)
devToReactPlugin()
// B) string shorthand
devToReactPlugin('MyCard')
// C) object map (recommended, required in prod)
devToReactPlugin({
MyCard: 'src/components/MyCard.tsx',
MyHeader: 'src/components/Header.tsx',
})// Option 1: origin + name (recommended)
<ReactLoader
origin="http://localhost:5173"
name="MyCard"
componentProps={{ title: 'Title' }}
/>
// Option 2: direct URL
<ReactLoader
url="http://localhost:5173/@fs/path/to/MyCard.tsx"
componentProps={{ title: 'Title' }}
/>http://localhost:5173/__dev_to__/debug.html
Discovery JSON:
http://localhost:5173/__dev_to__/discovery.json
dev-to build
# or: vite build --mode libIf you used create-dev-to, the scaffold includes a build:lib script (it runs dev-to build):
pnpm build:libYou can forward any Vite build flags, for example:
dev-to build --sourcemap --outDir dist-libOutput example:
dist/
MyCard/
MyCard.js
MyCard.css
MyCard.d.ts
UMD bundles can be used anywhere:
<script src="https://cdn.example.com/react.js"></script>
<script src="https://cdn.example.com/react-dom.js"></script>
<script src="/dist/MyCard/MyCard.js"></script>
<script>
const { MyCard } = window.MyCard
</script>devToReactPlugin(componentMap, {
open: false,
css: {
modules: {
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
build: {
minify: true,
sourcemap: true,
},
})interface ReactLoaderProps {
origin?: string
name?: string
url?: string
componentProps?: Record<string, any>
contractEndpoint?: string
}git clone https://github.com/YangYongAn/dev-to.git
cd dev-to
pnpm installpnpm build
pnpm dev
pnpm lint
pnpm test# Terminal 1
cd packages/react-template
pnpm dev
# Terminal 2
cd packages/react-playground
pnpm devScope: packages with private: false (@dev-to/react-shared, @dev-to/react-plugin, @dev-to/react-loader, create-dev-to).
Workflow:
- Implement the change and test locally.
- Create a changeset:
pnpm changeset. - Open a PR and merge into
main. - CI (
.github/workflows/ci.yml) runs the release pipeline and opens/updates a release PR. The PR title includes versions, for example:chore(repo): release packages (@dev-to/react-plugin@0.1.2). - Merge the release PR to publish to npm and push tags.
Manual (only if CI is unavailable):
pnpm version
pnpm release
git push --follow-tagsScope: packages/website (no changesets).
Versioning is derived from conventional commits since the last website-v* tag:
type!orBREAKING CHANGE-> majorfeat-> minorfix/perf-> patch
Workflow:
- Merge website changes into
main. - CI deploys a Vercel preview and (if release-worthy commits exist) opens/updates a
website-releasePR with the preview URL and version. - Review the preview, then merge the
website-releasePR. - CI deploys production and creates a GitHub release tag
website-vX.Y.Z.
Details: packages/website/DEPLOYMENT.md.
This repo uses Conventional Commits and requires a scope. The scope must be a package directory or one of repo, deps, ci.
Examples:
feat(react-plugin): add debug panel
fix(react-loader): resolve HMR timing
docs(repo): update README
feat(website): refresh homepage copy- AI agent platforms where each team ships its own agent card.
- Micro-frontend platforms that load React cards on demand.
- Low-code platforms with custom component plugins.
- Electron apps that load remote plugins.
- Fork the repo.
- Create a feature branch.
- Commit changes.
- Push and open a PR.
MIT (c) YangYongAn
Do I need CORS?
The host app and Vite Dev Server usually run on different ports, so you must enable server.cors: true in Vite.
How do I use it in production?
Two options:
- Build UMD bundles with
dev-to build(equivalent tovite build --mode lib) and distribute via CDN or static hosting. - Run Vite Dev Server in production (not recommended, only for internal tools).
Will Vue/Svelte be supported?
React is supported today. The architecture is framework-agnostic, so other frameworks can be added later.
How do I avoid style conflicts?
CSS Modules is recommended. The plugin generates stable scoped class names to reduce collisions.
HMR is not working. What should I check?
Checklist:
server.corsis enabled in Vite.- The host app loads the runtime (ReactLoader handles this automatically).
- Check browser console errors.
- Use the debug panel to inspect status.