Compose a view
Use functions, typed props, and async data to build reusable HTML components.
Write your first componentCompose typed, async components in your existing server. Start with an HTML response, then let slower parts of the page arrive when they are ready.
npm install @vincle/corebun add @vincle/coreimport { renderToString } from "@vincle/core";
function App({ name }: { name: string }) { return <h1>Hello, {name}!</h1>;}
const page = <App name="world" />;const html = await renderToString(page);<h1>Hello, world!</h1>The rendered output is a plain HTML string.
Keep your server and routing. Choose how much rendering behavior each page needs.
Use functions, typed props, and async data to build reusable HTML components.
Write your first componentRender with @vincle/core and send the HTML from your existing HTTP handler.
Connect a view to your serverAdd @vincle/flow to send the page shell first, then deliver deferred HTML fragments.
Stream a fragmentKeep the heading visible while an async component loads. With flow, a fallback fills the space until its HTML is ready.
Choose how it is delivered: natively, or through an HTMX or Turbo adapter.
Follow the complete exampleimport { Defer, renderToStream } from "@vincle/flow";import { NativeAdapter } from "@vincle/flow/adapters";
async function findResults() { return [{ title: "Getting started", href: "/guide/getting-started/installation" }];}
async function Results() { const items = await findResults(); return ( <ul> {items.map((item) => ( <li> <a href={item.href}>{item.title}</a> </li> ))} </ul> );}
function Page() { return ( <main> <h1>Search results</h1> <Defer fallback={<p>Loading results…</p>}> <Results /> </Defer> </main> );}
const stream = renderToStream(() => <Page />, NativeAdapter);The Results component stays the same. The page opts into deferred rendering.
Typed views, predictable rendering, and explicit HTML boundaries.
View source on GitHubFetch data inside the component that needs it. Vincle awaits the tree.
Share a value with a subtree through a React-style context Provider, or keep per-request state in a Scope.
Content is escaped by default, dangerous URL schemes are blocked, and function-valued attributes are refused.
Write components and HTML attributes with TypeScript checking your work.