|
| 1 | +--- |
| 2 | +title: "Vibe Coding" |
| 3 | +description: "Build AI-powered app generators that turn natural language into running code using E2B sandboxes for secure execution and live previews." |
| 4 | +icon: "wand-magic-sparkles" |
| 5 | +--- |
| 6 | + |
| 7 | +Vibe coding tools let users describe an app in plain language and get back running code instantly. The challenge is executing AI-generated code safely — it could be buggy, resource-hungry, or malicious. E2B sandboxes solve this by providing isolated environments where generated code runs securely, with [public URLs](/docs/sandbox/internet-access) for live previews that users can open in their browser. |
| 8 | + |
| 9 | +For a complete working implementation, see [Fragments](https://github.com/e2b-dev/fragments) — an open-source vibe coding platform you can try via the [live demo](https://fragments.e2b.dev). |
| 10 | + |
| 11 | +## How It Works |
| 12 | + |
| 13 | +1. **User describes what they want** — e.g., "Build a todo app with dark mode" or "Create a chart of monthly sales data" |
| 14 | +2. **Your backend sends the prompt to an LLM** — any model that can generate code (OpenAI, Anthropic, Google, Mistral, etc.) |
| 15 | +3. **The LLM returns structured output** — generated code, a list of additional dependencies, and which framework to target |
| 16 | +4. **Your backend creates an E2B sandbox** — using a pre-configured [template](/docs/template/quickstart) that matches the target framework (e.g., Next.js, Streamlit, Python) |
| 17 | +5. **Dependencies are installed** — `commands.run()` installs any extra packages the LLM requested |
| 18 | +6. **Generated code is written to the sandbox** — `files.write()` places the code at the correct file path |
| 19 | +7. **The app starts and becomes accessible** — `getHost(port)` / `get_host(port)` returns a public URL the user can open in their browser |
| 20 | + |
| 21 | +## Install the E2B SDK |
| 22 | + |
| 23 | +The [E2B SDK](https://github.com/e2b-dev/e2b) lets you create sandboxes, write files, run commands, and retrieve public URLs for running apps. |
| 24 | + |
| 25 | +<CodeGroup> |
| 26 | +```bash JavaScript & TypeScript |
| 27 | +npm i e2b |
| 28 | +``` |
| 29 | +```bash Python |
| 30 | +pip install e2b |
| 31 | +``` |
| 32 | +</CodeGroup> |
| 33 | + |
| 34 | +## Core Implementation |
| 35 | + |
| 36 | +The following snippets show the key building blocks for a vibe coding backend, adapted from [Fragments](https://github.com/e2b-dev/fragments). |
| 37 | + |
| 38 | +### Creating a sandbox from a template |
| 39 | + |
| 40 | +Create a sandbox from a [custom template](/docs/template/quickstart) that has your target framework pre-installed. The template's start command (e.g., `npx next --turbo`) launches the dev server automatically, so the app is ready to serve as soon as the sandbox starts. See the [Next.js template example](/docs/template/examples/nextjs) for a full template definition. |
| 41 | + |
| 42 | +<CodeGroup> |
| 43 | +```typescript JavaScript & TypeScript |
| 44 | +import { Sandbox } from 'e2b' |
| 45 | + |
| 46 | +// Create a sandbox from a pre-configured Next.js template |
| 47 | +// The dev server starts automatically via the template's start command |
| 48 | +const sandbox = await Sandbox.create('nextjs-app', { |
| 49 | + timeoutMs: 300_000, // 5 minutes |
| 50 | +}) |
| 51 | + |
| 52 | +console.log('Sandbox created:', sandbox.sandboxId) |
| 53 | +``` |
| 54 | +```python Python |
| 55 | +from e2b import Sandbox |
| 56 | + |
| 57 | +# Create a sandbox from a pre-configured Next.js template |
| 58 | +# The dev server starts automatically via the template's start command |
| 59 | +sandbox = Sandbox.create("nextjs-app", timeout=300) # 5 minutes |
| 60 | + |
| 61 | +print("Sandbox created:", sandbox.sandbox_id) |
| 62 | +``` |
| 63 | +</CodeGroup> |
| 64 | + |
| 65 | +### Installing dependencies |
| 66 | + |
| 67 | +The LLM may request packages that aren't included in the template. Install them at runtime with `commands.run()` before writing the generated code. See [Install custom packages](/docs/quickstart/install-custom-packages) for more details. |
| 68 | + |
| 69 | +<CodeGroup> |
| 70 | +```typescript JavaScript & TypeScript |
| 71 | +import { Sandbox } from 'e2b' |
| 72 | + |
| 73 | +const sandbox = await Sandbox.create('nextjs-app', { timeoutMs: 300_000 }) |
| 74 | + |
| 75 | +// Install additional packages requested by the LLM |
| 76 | +const dependencies = ['recharts', '@radix-ui/react-icons'] |
| 77 | +await sandbox.commands.run(`npm install ${dependencies.join(' ')}`) |
| 78 | +``` |
| 79 | +```python Python |
| 80 | +from e2b import Sandbox |
| 81 | + |
| 82 | +sandbox = Sandbox.create("nextjs-app", timeout=300) |
| 83 | + |
| 84 | +# Install additional packages requested by the LLM |
| 85 | +dependencies = ["recharts", "@radix-ui/react-icons"] |
| 86 | +sandbox.commands.run(f"npm install {' '.join(dependencies)}") |
| 87 | +``` |
| 88 | +</CodeGroup> |
| 89 | + |
| 90 | +### Writing generated code |
| 91 | + |
| 92 | +Once the LLM generates code, write it to the correct file path in the sandbox. The sandbox [filesystem](/docs/filesystem/read-write) works like a standard Linux machine — place the file where the framework expects it. |
| 93 | + |
| 94 | +<CodeGroup> |
| 95 | +```typescript JavaScript & TypeScript |
| 96 | +import { Sandbox } from 'e2b' |
| 97 | + |
| 98 | +const sandbox = await Sandbox.create('nextjs-app', { timeoutMs: 300_000 }) |
| 99 | + |
| 100 | +// Write the LLM-generated code to the sandbox filesystem |
| 101 | +const generatedCode = ` |
| 102 | +export default function Home() { |
| 103 | + return ( |
| 104 | + <div className="flex min-h-screen items-center justify-center"> |
| 105 | + <h1 className="text-4xl font-bold">Hello from AI</h1> |
| 106 | + </div> |
| 107 | + ) |
| 108 | +} |
| 109 | +` |
| 110 | + |
| 111 | +await sandbox.files.write('/home/user/pages/index.tsx', generatedCode) |
| 112 | +``` |
| 113 | +```python Python |
| 114 | +from e2b import Sandbox |
| 115 | + |
| 116 | +sandbox = Sandbox.create("nextjs-app", timeout=300) |
| 117 | + |
| 118 | +# Write the LLM-generated code to the sandbox filesystem |
| 119 | +generated_code = """ |
| 120 | +export default function Home() { |
| 121 | + return ( |
| 122 | + <div className="flex min-h-screen items-center justify-center"> |
| 123 | + <h1 className="text-4xl font-bold">Hello from AI</h1> |
| 124 | + </div> |
| 125 | + ) |
| 126 | +} |
| 127 | +""" |
| 128 | + |
| 129 | +sandbox.files.write("/home/user/pages/index.tsx", generated_code) |
| 130 | +``` |
| 131 | +</CodeGroup> |
| 132 | + |
| 133 | +### Getting the preview URL |
| 134 | + |
| 135 | +After writing the code, the dev server (already running via the template's start command) picks up the changes automatically. Retrieve the sandbox's [public URL](/docs/sandbox/internet-access) and send it to your frontend so the user can see the running app. |
| 136 | + |
| 137 | +<CodeGroup> |
| 138 | +```typescript JavaScript & TypeScript |
| 139 | +import { Sandbox } from 'e2b' |
| 140 | + |
| 141 | +const sandbox = await Sandbox.create('nextjs-app', { timeoutMs: 300_000 }) |
| 142 | + |
| 143 | +// ... install dependencies and write code ... |
| 144 | + |
| 145 | +// Get the public URL for the running app |
| 146 | +// The Next.js dev server runs on port 3000 (configured in the template) |
| 147 | +const host = sandbox.getHost(3000) |
| 148 | +const previewUrl = `https://${host}` |
| 149 | +console.log('Preview your app at:', previewUrl) |
| 150 | +``` |
| 151 | +```python Python |
| 152 | +from e2b import Sandbox |
| 153 | + |
| 154 | +sandbox = Sandbox.create("nextjs-app", timeout=300) |
| 155 | + |
| 156 | +# ... install dependencies and write code ... |
| 157 | + |
| 158 | +# Get the public URL for the running app |
| 159 | +# The Next.js dev server runs on port 3000 (configured in the template) |
| 160 | +host = sandbox.get_host(3000) |
| 161 | +preview_url = f"https://{host}" |
| 162 | +print("Preview your app at:", preview_url) |
| 163 | +``` |
| 164 | +</CodeGroup> |
| 165 | + |
| 166 | +### Putting it all together |
| 167 | + |
| 168 | +Here is a complete example that demonstrates the full vibe coding flow: prompting an LLM, creating a sandbox, installing dependencies, writing the generated code, and returning a preview URL. This is a simplified version of how [Fragments](https://github.com/e2b-dev/fragments) handles each generation request. |
| 169 | + |
| 170 | +<CodeGroup> |
| 171 | +```typescript JavaScript & TypeScript expandable |
| 172 | +import { Sandbox } from 'e2b' |
| 173 | +import OpenAI from 'openai' |
| 174 | + |
| 175 | +// --- 1. Get code from the LLM --- |
| 176 | +const openai = new OpenAI() |
| 177 | +const response = await openai.chat.completions.create({ |
| 178 | + model: 'gpt-5.2-mini', |
| 179 | + messages: [ |
| 180 | + { |
| 181 | + role: 'system', |
| 182 | + content: |
| 183 | + 'You are a frontend developer. Generate a single Next.js page component using TypeScript and Tailwind CSS. Return only the code, no markdown.', |
| 184 | + }, |
| 185 | + { |
| 186 | + role: 'user', |
| 187 | + content: 'Build a calculator app with a clean design', |
| 188 | + }, |
| 189 | + ], |
| 190 | +}) |
| 191 | + |
| 192 | +const generatedCode = response.choices[0].message.content |
| 193 | +const dependencies = [''] // The LLM could also return a dependency list |
| 194 | + |
| 195 | +// --- 2. Create a sandbox from the Next.js template --- |
| 196 | +const sandbox = await Sandbox.create('nextjs-app', { |
| 197 | + timeoutMs: 300_000, |
| 198 | +}) |
| 199 | + |
| 200 | +// --- 3. Install any additional dependencies --- |
| 201 | +if (dependencies.length > 0 && dependencies[0] !== '') { |
| 202 | + await sandbox.commands.run(`npm install ${dependencies.join(' ')}`) |
| 203 | +} |
| 204 | + |
| 205 | +// --- 4. Write the generated code --- |
| 206 | +await sandbox.files.write('/home/user/pages/index.tsx', generatedCode) |
| 207 | + |
| 208 | +// --- 5. Get the preview URL --- |
| 209 | +const host = sandbox.getHost(3000) |
| 210 | +const previewUrl = `https://${host}` |
| 211 | +console.log('App is live at:', previewUrl) |
| 212 | + |
| 213 | +// Later, when the user is done: |
| 214 | +await sandbox.kill() |
| 215 | +``` |
| 216 | +```python Python expandable |
| 217 | +from e2b import Sandbox |
| 218 | +from openai import OpenAI |
| 219 | + |
| 220 | +# --- 1. Get code from the LLM --- |
| 221 | +client = OpenAI() |
| 222 | +response = client.chat.completions.create( |
| 223 | + model="gpt-5.2-mini", |
| 224 | + messages=[ |
| 225 | + { |
| 226 | + "role": "system", |
| 227 | + "content": "You are a frontend developer. Generate a single Next.js page component using TypeScript and Tailwind CSS. Return only the code, no markdown.", |
| 228 | + }, |
| 229 | + { |
| 230 | + "role": "user", |
| 231 | + "content": "Build a calculator app with a clean design", |
| 232 | + }, |
| 233 | + ], |
| 234 | +) |
| 235 | + |
| 236 | +generated_code = response.choices[0].message.content |
| 237 | +dependencies = [] # The LLM could also return a dependency list |
| 238 | + |
| 239 | +# --- 2. Create a sandbox from the Next.js template --- |
| 240 | +sandbox = Sandbox.create("nextjs-app", timeout=300) |
| 241 | + |
| 242 | +# --- 3. Install any additional dependencies --- |
| 243 | +if dependencies: |
| 244 | + sandbox.commands.run(f"npm install {' '.join(dependencies)}") |
| 245 | + |
| 246 | +# --- 4. Write the generated code --- |
| 247 | +sandbox.files.write("/home/user/pages/index.tsx", generated_code) |
| 248 | + |
| 249 | +# --- 5. Get the preview URL --- |
| 250 | +host = sandbox.get_host(3000) |
| 251 | +preview_url = f"https://{host}" |
| 252 | +print("App is live at:", preview_url) |
| 253 | + |
| 254 | +# Later, when the user is done: |
| 255 | +sandbox.kill() |
| 256 | +``` |
| 257 | +</CodeGroup> |
| 258 | + |
| 259 | +1. **Get code from the LLM** — send a prompt to any model; the LLM returns generated code and optionally a list of dependencies — swap the model for any provider via [Connect LLMs](/docs/quickstart/connect-llms) |
| 260 | +2. **Create a sandbox** — `Sandbox.create('nextjs-app')` spins up an isolated environment from a [custom template](/docs/template/quickstart) with the framework pre-installed and a dev server already running |
| 261 | +3. **Install dependencies** — `commands.run()` installs any extra packages the LLM requested at runtime |
| 262 | +4. **Write generated code** — `files.write()` places the code in the sandbox [filesystem](/docs/filesystem/read-write) at the path the framework expects |
| 263 | +5. **Get the preview URL** — `getHost(3000)` / `get_host(3000)` returns a public hostname; combine with `https://` to form the URL your frontend embeds in an iframe or opens in a new tab |
| 264 | + |
| 265 | +## Related Guides |
| 266 | + |
| 267 | +<CardGroup cols={3}> |
| 268 | + <Card title="Custom Templates" icon="cube" href="/docs/template/quickstart"> |
| 269 | + Pre-install frameworks and tools so sandboxes start instantly |
| 270 | + </Card> |
| 271 | + <Card title="Connect LLMs" icon="brain" href="/docs/quickstart/connect-llms"> |
| 272 | + Integrate AI models with sandboxes using tool calling |
| 273 | + </Card> |
| 274 | + <Card title="Internet Access" icon="globe" href="/docs/sandbox/internet-access"> |
| 275 | + Access sandbox apps via public URLs and control network policies |
| 276 | + </Card> |
| 277 | +</CardGroup> |
0 commit comments