Getting Started
Build your first Uniview plugin in 5 minutes
This guide walks you through creating a simple plugin and rendering it in a Svelte host.
Prerequisites
- Node.js 18+
- pnpm (recommended) or npm
Installation
Install the core packages:
# For plugin development
pnpm add @uniview/runtime @uniview/react-renderer @uniview/protocol react
# For host development (Svelte)
pnpm add @uniview/host-sdk @uniview/host-svelte @uniview/protocolCreating a Plugin
1. Write Your React Component
Create a standard React component. You can use hooks, state, and props as usual.
import { useState } from "react";
interface Props {
initialCount?: number;
}
export default function App({ initialCount = 0 }: Props) {
const [count, setCount] = useState(initialCount);
return (
<div className="p-4 space-y-4">
<h1 className="text-xl font-bold">Counter Plugin</h1>
<p>Current count: {count}</p>
<div className="flex gap-2">
<button
onClick={() => setCount((c) => c - 1)}
className="px-4 py-2 bg-red-500 text-white rounded"
>
-
</button>
<button
onClick={() => setCount((c) => c + 1)}
className="px-4 py-2 bg-green-500 text-white rounded"
>
+
</button>
</div>
</div>
);
}2. Create the Worker Entry Point
Bootstrap your plugin using the runtime:
import { startWorkerPlugin } from "@uniview/runtime";
import App from "./App";
startWorkerPlugin({ App });3. Build the Plugin
Bundle for browser (Web Worker target):
// Using Bun
await Bun.build({
entrypoints: ["./src/worker.ts"],
outdir: "./dist",
target: "browser",
format: "esm",
minify: true,
});Or with other bundlers (esbuild, Vite, etc.):
esbuild src/worker.ts --bundle --format=esm --outfile=dist/plugin.jsThe plugin bundle must be self-contained with all dependencies included. Web Workers can't access the host's modules.
Creating a Host (Svelte)
1. Set Up the Controller
<script lang="ts">
import { PluginHost } from '@uniview/host-svelte';
import { createWorkerController, createComponentRegistry } from '@uniview/host-sdk';
import type { Component } from 'svelte';
// Create component registry (for custom components)
const registry = createComponentRegistry<Component>();
// Create controller pointing to your plugin
const controller = createWorkerController({
pluginUrl: '/plugins/counter.js'
});
</script>
<div class="p-8">
<h1 class="text-2xl font-bold mb-4">Uniview Docs</h1>
<PluginHost {controller} {registry}>
{#snippet loading()}
<p>Loading plugin...</p>
{/snippet}
</PluginHost>
</div>2. Serve the Plugin
Place your built plugin in static/plugins/ (for SvelteKit) or configure your dev server to serve it.
3. Run the App
pnpm devYour plugin should now render inside the host!
Custom Components
By default, plugins can use HTML elements (div, button, input, etc.). For custom components:
Plugin Side
Create wrapper components that emit custom types:
import { createElement } from "react";
export function Button({ title, onClick, variant = "primary" }) {
return createElement("Button", { title, onClick, variant });
}Host Side
Register renderers for custom types:
<script lang="ts">
import { Button } from '$lib/components/ui/button';
let { title, onclick, variant }: Props = $props();
</script>
<Button {variant} on:click={onclick}>
{title}
</Button>// In your page
registry.register("Button", PluginButton);
registry.register("Card", PluginCard);
// etc.Runtime Modes
Uniview supports three runtime modes:
| Mode | Use Case | Security |
|---|---|---|
| Worker | Production, untrusted plugins | Sandboxed |
| WebSocket | Server-side plugins, Node.js APIs | Network isolated |
| Main Thread | Development, debugging | None |
// Worker mode (default, production)
const controller = createWorkerController({
pluginUrl: "/plugin.js",
});
// WebSocket mode (server-side plugins via Bridge)
const controller = createWebSocketController({
serverUrl: "ws://localhost:3000", // Bridge server
pluginId: "my-plugin", // Required for routing
});
// Main thread mode (development only)
import App from "./plugin/App";
const controller = createMainController({ App });Running the Example
The quickest way to see all modes in action:
# From the repository root
pnpm install && pnpm build
# Run the complete example
cd examples/host-svelte-demo
pnpm dev:allThis starts:
- Bridge server on
:3000- Shared WebSocket multiplexer (from@uniview/bridge-server) - Plugin clients - Node.js plugins connect to bridge
- SvelteKit host on
:5173- The UI
Open http://localhost:5173 and toggle between "Worker" and "Node.js" modes to see both in action.