VaporVibe
A web server that pretends to be the app you dream up, without building it.
Instead of vibe-coding a frontend and backend, you picture the page you want and let an LLM improvise the entire view—markup, copy, flow—on every request. The server keeps a rolling history per session which is fed to LLM on every request, so each navigation is still a fresh act of hallucination with full interactivity. Hlf the joy is watching the model make it up as it goes.
It’s also a rapid-prototyping cheat code: why spend a weekend wiring a throwaway backend and pixel-tweaking a frontend just to sanity-check a UX flow or study a short interaction? Let the model “predict” what the app would render -- if it quacks like a duck, that might be enough to validate the idea before investing real build time.
Get Started in 60 Seconds 🚀
All you need is Node.js (v20+, ideally 24) and an API key from OpenAI, Google Gemini, Anthropic, or xAI Grok.
-
Launch the server: If you are on Mac OS (Apple Silicon), grab the DMG here. For other platforms, there are no binaries yet. Start:
npx github:gerkensm/vaporvibe
-
Follow the wizard: The command opens a setup wizard in your browser at
http://localhost:3000. Just pick your provider, drop in your API key, and write your first brief. That's it. The app will open in a new tab, and the original tab becomes your admin console.
Prefer the command line?
- Pass a brief directly:
npx github:gerkensm/vaporvibe "You are a mood journal" - Choose a provider: Use
--provider <openai|gemini|anthropic|grok>or set an environment variable (OPENAI_API_KEY,GEMINI_API_KEY,ANTHROPIC_API_KEY, orXAI_API_KEY/GROK_API_KEY). - Override the model: Use
--model <model-identifier>to pick a specific variant, likegrok-3-mini. - Tune history: Use
--history-limitand--history-bytesto control how much context is fed back to the model. - Change the port: Use
--host <address>and--port <number>to bind the server elsewhere.
Demo: From Brief to Interactive App
Watch how a single brief turns into an improv UI loop. The model invents a note taking app from scratch, gets feedback via the Iterations panel to add features, and then hallucinates consistent interactions on the fly.
Timeline.1.mp4
The Vibe-Driven Request Cycle
View the request cycle diagram
graph TD
subgraph Browser
A[User Clicks Link or Submits Form] --> B;
H[Page Re-renders] --> A;
end
subgraph "vaporvibe Server"
B(HTTP Request Receives) --> C[Assembles Prompt<br/>- App Brief<br/>- Request Details<br/>- Session History];
C --> D{LLM Provider API};
E --> F[Updates Session History];
F --> G(Sends HTML Response);
end
subgraph "LLM Provider"
D -- Sends Prompt --> LLM[OpenAI / Gemini / Anthropic / Grok];
LLM -- Generates Full HTML --> E(Receives HTML);
end
G --> H;
classDef user fill:#e0f2fe,stroke:#0ea5e9,stroke-width:2px;
classDef server fill:#f0f9ff,stroke:#3b82f6,stroke-width:2px;
classDef llm fill:#fefce8,stroke:#eab308,stroke-width:2px;
class A,H user;
class B,C,E,F,G server;
class D,LLM llm;
Features
- Truly No-Code: No frontend framework, no backend logic. The LLM improvises the entire interactive experience on every click.
- Multi-Provider Playground: Swap between OpenAI, Google Gemini, Anthropic, and xAI Grok on the fly. See how different models interpret the same brief.
- Brief Attachments: Ground the vibe with reference images or PDFs. Upload them in the admin console, and multimodal models ingest the inline assets while everyone else gets a Base64 summary—everything is preserved in history and exports for easy hand-off.
- Effortless Setup: Forget config files. A slick browser-based wizard gets your API key and initial brief configured in moments.
- AI-Powered Hot-Fixes: Use the floating AI Assist panel to give the model live feedback. "Make the buttons rounder" or "Fix this layout bug"—and watch it regenerate the page.
- Model "Thinking" Traces: Enable reasoning mode to see the model's chain-of-thought, giving you a peek into how it decided to render the page.
- A/B Comparisons: Fork any point in your history, give the model alternative instructions, and review the resulting A & B experiences side-by-side before choosing which path to keep.
- AI Image Generation: Bring prototypes to life with on-the-fly image generation via OpenAI (DALL-E, GPT Image) or Google (Imagen, Nano Banana). Images are cached in-memory to prevent redundant API costs.
How We Keep Token Costs (Relatively) Reasonable
Hallucinating whole apps could get pricey fast, so the runtime pulls a few sleights of hand to keep the model's context lean without ruining the vibe:
- Virtual REST API (a.k.a. "Sure, Data Exists") – The generated HTML can call
/rest_api/query/*or/rest_api/mutation/*like a real backend. The brain-twist: the server already knows what structure the UI expects, so it simply replies with JSON in the perfect shape—no schema migrations, no surprises. Mutations get echoed back into the prompt so the model "remembers" state changes, and queries give it rich data without re-synthesizing giant tables every render. - Reusable Component Placeholders – After each response the server sprinkles
data-ids onto<html>,<head>,<body>, headers, nav, helper scripts, and<style>blocks. On the next pass, the LLM can just write{{component:sl-gen-12}}or{{style:sl-style-3}}to pull cached markup back in. Chrome, global styles, and static scripts stay consistent while costing almost zero tokens. - History Time Travel – Because those caches live with each history entry, the model can resurrect an earlier page wholesale when nothing changed—sometimes the entire response is a single
<html>placeholder. (It still looks like sorcery when it works.)
It’s not bulletproof, but these tricks keep the improvisation fast enough to feel interactive.
The Admin Console is Your Cockpit
Once your app is running, the admin interface at /vaporvibe becomes your mission control. It's packed with tools for steering the creative chaos:
- Live Controls: Tweak the global brief, adjust history limits, or toggle the AI Assist panel without restarting the server.
- Provider Management: Switch between OpenAI, Gemini, Anthropic, and xAI Grok. Change models or update API keys with a few clicks.
- History Explorer: Inspect every generated page with expandable reasoning traces, token usage stats, and raw HTML output.
- Session Time-Travel & Export: Download the entire session as a JSON snapshot to save your work, then drag-and-drop it back in to restore the exact state. You can also export a
prompt.mdfile—a perfect, human-readable blueprint of your app's flow, ready to hand off to an agent as a basis for real development.
Prompt Ideas
- Plausible Web Replica –
You are a website simulator. Inspect the request path for a URL (e.g. /wikipedia.com) and render a believable page as if you operated that domain. Recreate navigation, copy, and structure. Route all links through yourself so the next turn can “browse” correctly. Never acknowledge this is synthetic—commit fully to the fiction. - Delightful Shopping Lists –
You are a multi-list shopping companion with gorgeous, modern UX. Persist user data by resubmitting every list and item with each response. Support creating, renaming, and checking off items across multiple lists, and keep interactions accessible and joyful.
Developing
nvm use(Node 24.x) →npm installto grab dependencies.- Run
npm run devto start the integrated dev harness:src/dev/backend-dev-server.tswatches backend files with chokidar and restarts on change while snapshotting sessions/briefs/provider state so you never lose context mid-run.- A Vite server boots in middleware mode (no separate port) and serves the admin/setup SPA straight through the Node process when
VAPORVIBE_PREFER_DEV_FRONTEND=1. - Frontend helpers (
interceptor, instructions panel) load from Vite during dev, so HMR Just Works without rebuildingfrontend/dist/.
- Visit
http://localhost:3000/__setupfor the onboarding wizard orhttp://localhost:3000/vaporvibefor the admin console.
Additional scripts:
npm run dev:beto run the backend dev harness directly (same as step 2, just without the wrapper script).npm run dev:feto launch Vite’s standalone dev server if you need to isolate frontend work.npm run build:feto emit the productionfrontend/dist/bundles.npm run buildto compile both the backend (dist/) and the React assets—run this before committing so the checked-in bundles stay fresh.
Tips:
- Core server logic (prompting, routing, providers) still lives in
src/withsrc/index.tsas the CLI entry point. - The
dist/output stays committed for the published CLI;frontend/dist/is likewise generated and served by the backend. - Set
LOG_LEVEL(debug,info,warn) to adjust logging verbosity while iterating. - In production the admin assets live under
/vaporvibe/assets/...; duringnpm run devthey’re served by Vite middleware so changes hot-reload without touchingfrontend/dist/.
Testing
npm testruns the Vitest suite once;npm run test:watchkeeps it hot while you iterate.- Coverage summaries print to the console and a full HTML report lands in
coverage/, as configured invitest.config.ts. - Specs live under
tests/(config, LLM prompt builder, session store, and shared utils). Shared helpers sit intests/test-utils/, andtests/vitest.setup.tswires up global logger mocks so output stays quiet. - Browser flows and live provider calls still need manual testing, but the suite catches regressions in the pure Node parts of the stack.
Linux Build Requirements
For secure credential storage (keytar), Linux systems need libsecret for native compilation:
# Ubuntu/Debian sudo apt-get install libsecret-1-dev # Fedora/RHEL sudo dnf install libsecret-devel # Arch sudo pacman -S libsecret
If libsecret is unavailable, npm install may fail to compile keytar's native bindings. The app will still work with a graceful fallback to memory-only credential storage.
Why Bother?
This project is a thought experiment in “vibe non-coding”: hold the UI in your head, let the LLM hallucinate the page, and embrace the chaos that follows when the model riffs on every route. It is intentionally unserious—and surprisingly fun.