# Build a single-file HTML prototype

Ollav hosts **one self-contained HTML file** per document, up to 15 MB. Hand-written prototypes usually already are one. A Vite, React or Vue project needs a build step that inlines everything into `index.html`.

## Vite (React, Vue, Svelte, vanilla)

```bash
npm install -D vite-plugin-singlefile
```

```js
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { viteSingleFile } from "vite-plugin-singlefile";

export default defineConfig({
  plugins: [react(), viteSingleFile()],
});
```

```bash
npm run build      # → dist/index.html with JS, CSS and small assets inlined
```

Then upload the file. With curl it costs an agent no tokens:

```bash
curl -F "file=@dist/index.html" -H "Authorization: Bearer $OLLAV_API_KEY" -H "X-Ollav-Client: agent" https://app.ollav.app/api/documents
```

## Routing

Client-side routing works. Every sub-path of a document serves the same file, so reloading `/p/<slug>/settings` doesn't 404. With React Router either:

- use `HashRouter`, the simplest option, which always restores the exact route, or
- use `BrowserRouter` with `basename` set to the document path.

## Keeping it under 15 MB

Inlined images are base64, about a third larger than the original file. Most oversized builds are screenshots:

- convert PNG screenshots to WebP at quality 80
- downscale anything wider than about 2000 px
- load big media from an absolute URL instead of inlining it

## Things that won't work

- **Relative asset paths** (`src="assets/app.js"`). Only the one file is uploaded. Ollav returns a warning when it spots them.
- **Server code.** API routes, SSR and databases don't run. Call external CORS-friendly APIs from the browser instead.
- **A `<base href>` pointing elsewhere.** It breaks relative links. Ollav warns about this too.

[Share it](https://app.ollav.app) · [Agent quickstart](https://ollav.app/docs/agents)
