Skip to content

Getting started

Quick start

Create a Vidact project, write your first component, and build it for production in a few minutes.

This page walks you through a minimal client-side Vidact application with Vite. By the end you will have a working counter, a development server with hot reloading, and a production build you can deploy to any static host.

You need Node.js 24 or newer and a package manager. The examples use pnpm, but npm and yarn work the same way.

1. Create a project

The fastest way is the generator, which writes the whole project for you:

shell
npx vidact

It asks for a template: a single-page app, a full-stack Vidact Start app, or the same full-stack app served by Nitro so it deploys anywhere Nitro does. Then it leaves you with a project you can run. If you take that path, skip ahead to step 5.

Notice what is not on that list: react and react-dom. Your source code imports from react, but the Vidact Vite plugin resolves those imports to the compiled runtime. React itself is never installed or shipped.

2. Configure Vite and TypeScript

Add the Vidact plugin to a Vite config. The plugin compiles every .tsx file in your project.

vite.config.ts
import { vidact } from '@vidact/vite'import { defineConfig } from 'vite'export default defineConfig({  plugins: [vidact()],})

Then tell TypeScript to leave JSX alone (the compiler handles it) and to type JSX with Vidact's React-shaped types.

tsconfig.json
{  "compilerOptions": {    "target": "ES2022",    "module": "ESNext",    "moduleResolution": "Bundler",    "strict": true,    "jsx": "preserve",    "jsxImportSource": "@vidact/react-types",    "types": ["@vidact/react-types", "vite/client"]  },  "include": ["src", "vite.config.ts"]}

3. Write a component

Create src/Counter.tsx. This is ordinary React code.

src/Counter.tsx
import { useState } from 'react'export function Counter() {  const [count, setCount] = useState(0)  return (    <main>      <h1>Count: {count}</h1>      <button onClick={() => setCount((value) => value + 1)}>Increment</button>    </main>  )}

When Vidact compiles this file, it creates the <main>, <h1>, and <button> elements once, and emits a single updater that rewrites the heading's text node whenever count changes. Clicking the button never calls Counter again.

4. Mount it

Create an HTML page with a host element and a module entry that mounts the component.

index.html
<!doctype html><html lang="en">  <body>    <div id="app"></div>    <script type="module" src="/src/main.ts"></script>  </body></html>
src/main.ts
import { mountCompiled } from '@vidact/runtime'import { Counter } from './Counter.tsx'const host = document.querySelector('#app')if (host === null) throw new Error('Missing #app')mountCompiled(Counter, host)

mountCompiled is the Vidact equivalent of createRoot(host).render(<Counter />). It takes the component itself, not a JSX element, because a compiled component is a factory that builds its own DOM.

5. Run it

Start the development server and open the printed URL.

shell
pnpm vite

Edit Counter.tsx and the page updates. When you are ready to deploy:

shell
pnpm vite buildpnpm vite preview

The dist folder contains static files you can serve from anywhere.

Next steps

You now have a working Vidact project. From here:

  • Read Thinking in Vidact to understand what "components run once" means for the code you write.
  • Work through the Learn section for state, events, lists, effects, and context.
  • If you want server rendering and routing, continue to Vidact Start.