# Vite and custom servers

How Bud connects to your pages, and what a custom server needs to do.

Bud waits for Vite's HTTP server and starts on its own port. Bud opens your pages in a headless browser and captures them; Vite's hot updates reach those pages like any other tab, so the canvas follows your edits. Your pages never receive Bud's API capability.

## Custom server rendering

If your server renders HTML itself, pass every document through `transformIndexHtml` with the original URL, so Vite's client and its hot updates reach the page:

```ts title="render.ts"
import type { ViteDevServer } from 'vite'

export async function render(vite: ViteDevServer, url: string, template: string, html: string) {
  let shell = await vite.transformIndexHtml(url, template)
  return shell.replace('<!--app-html-->', () => html)
}
```

Keep a real Vite HTTP server. Middleware mode without a listener isn't supported, and streamed HTML needs its own integration.

## Without Vite

For an app you run separately, set its origin and start Bud with the CLI:

```ts title="bud.config.ts"
import { defineConfig } from '@bud.sh/app'

export default defineConfig({
  routes: ['/', '/pricing'],
  target: { origin: 'http://127.0.0.1:3000' },
})
```

```sh
npx bud .
```

Without Vite, Bud reloads the captured pages whenever project files change.
