Write React. Ship the DOM.

Vidact compiles your function components and hooks into direct DOM operations. No Virtual DOM, no re-renders, no React in the bundle.

Every example below is ordinary React, compiled by Vidact and running on this page.

Counter.tsx
import { useState } from 'react'export function Counter() {  const [count, setCount] = useState(0)  return (    <div>      <button onClick={() => setCount(count + 1)}>        Increment      </button>      <output>Count: {count}</output>    </div>  )}
Result
Count: 0
Component calls
1
DOM mutations
0
Tree diffs
0

Counted live by a MutationObserver watching this demo.

How it works

1

Compile

The compiler maps every expression to the values it reads. Code it cannot compile stops the build at its exact line.

2

Mount once

The component runs a single time and builds its DOM. There is no render loop and no tree to diff.

3

Update surgically

A state write runs only the updaters that read it: a text node, an attribute, a list row.

Full-stack, the same way

Vidact Start adds file routes, server loaders, SSR, hydration, and client navigation, all generated by the same compiler, so server and browser output match by construction.

Explore Vidact Start
src/routes/products/$productId.tsx
import { defineFileRoute } from '@vidact/start'const loader = async ({ params }) => ({  product: await findProduct(params.productId),})export function ProductRoute({ loaderData }) {  return <h1>{loaderData.product.name}</h1>}export const Route = defineFileRoute({  loader,  component: ProductRoute,})

Vidact is in beta. What is supported is documented; what is not fails at build time.

Get started