Skip to main content

Next.js

Basic Next.js app with Tailwind and shadcn UI
template.ts
import { Template, waitForPort } from 'e2b'

export const template = Template()
  .fromNodeImage('21-slim')
  .setWorkdir('/home/user/nextjs-app')
  .runCmd(
    'npx create-next-app@14.2.30 . --ts --tailwind --no-eslint --import-alias "@/*" --use-npm --no-app --no-src-dir'
  )
  .runCmd('npx shadcn@2.1.7 init -d')
  .runCmd('npx shadcn@2.1.7 add --all')
  .runCmd(
    'mv /home/user/nextjs-app/* /home/user/ && rm -rf /home/user/nextjs-app'
  )
  .setWorkdir('/home/user')
  .setStartCmd('npx next --turbo', waitForPort(3000))

build.ts
import { Template } from 'e2b'
import { template as nextJSTemplate } from './template'

Template.build(nextJSTemplate, {
  alias: 'nextjs-app',
  cpuCount: 1,
  memoryMB: 1024,
  onBuildLogs: (logEntry) => console.log(logEntry.toString()),
})

Desktop

Basic Ubuntu Desktop with GUI and VNC access
template.ts
import { Template, waitForPort } from 'e2b'

export const template = Template()
  .fromUbuntuImage('22.04')
  // Desktop environment and system utilities
  .runCmd([
    'yes | unminimize',
    'apt-get update',
    'apt-get install -y \
      xserver-xorg \
      xorg \
      x11-xserver-utils \
      xvfb \
      x11-utils \
      xauth \
      xfce4 \
      xfce4-goodies \
      util-linux \
      sudo \
      curl \
      git \
      wget \
      python3-pip \
      xdotool \
      scrot \
      ffmpeg \
      x11vnc \
      net-tools \
      netcat \
      x11-apps \
      libreoffice \
      xpdf \
      gedit \
      xpaint \
      tint2 \
      galculator \
      pcmanfm',
    'apt-get clean',
    'rm -rf /var/lib/apt/lists/*',
  ])
  // Streaming server setup
  .runCmd([
    'git clone --branch e2b-desktop https://github.com/e2b-dev/noVNC.git /opt/noVNC',
    'ln -s /opt/noVNC/vnc.html /opt/noVNC/index.html',
    'git clone --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify',
  ])
  // Set default terminal
  .runCmd(
    'ln -sf /usr/bin/xfce4-terminal.wrapper /etc/alternatives/x-terminal-emulator'
  )
  .copy('start_command.sh', '/start_command.sh')
  .runCmd('chmod +x /start_command.sh')
  .setStartCmd('/start_command.sh', waitForPort(6080))

start_command.sh
#!/bin/bash

# Set display
export DISPLAY=${DISPLAY:-:0}

# Start Xvfb
Xvfb $DISPLAY -ac -screen 0 1024x768x24 -nolisten tcp &
sleep 2

# Start XFCE session
startxfce4 &
sleep 5

# Start VNC server
x11vnc -bg -display $DISPLAY -forever -wait 50 -shared -rfbport 5900 -nopw \
    -noxdamage -noxfixes -nowf -noscr -ping 1 -repeat -speeds lan &
sleep 2

# Start noVNC server
cd /opt/noVNC/utils && ./novnc_proxy --vnc localhost:5900 --listen 6080 --web /opt/noVNC --heartbeat 30 &
sleep 2
build.ts
import { Template } from 'e2b'
import { template as desktopTemplate } from './template'

await Template.build(desktopTemplate, {
  alias: 'desktop',
  cpuCount: 8,
  memoryMB: 8192,
  onBuildLogs: (logEntry) => console.log(logEntry.toString()),
})

Claude Code

Claude Code Agent in a Sandbox
template.ts
import { Template } from 'e2b'

export const template = Template()
  .fromNodeImage('24')
  .aptInstall(['curl', 'git', 'ripgrep'])
  // Claude Code will be available globally as "claude"
  .npmInstall('-g @anthropic-ai/claude-code@latest')

build.ts
import { Template } from 'e2b'
import { template as claudeCodeTemplate } from './template'

Template.build(claudeCodeTemplate, {
  alias: 'claude-code',
  cpuCount: 1,
  memoryMB: 1024,
  onBuildLogs: (logEntry) => console.log(logEntry.toString()),
})
sandbox.ts

import { Sandbox } from 'e2b'

const sbx = await Sandbox.create('claude-code', {
  envs: {
    ANTHROPIC_API_KEY: '<your api key>',
  },
})

console.log('Sandbox created', sbx.sandboxId)

// Print help for Claude Code
// const result = await sbx.commands.run('claude --help')
// console.log(result.stdout)

// Run a prompt with Claude Code
const result = await sbx.commands.run(
  `echo 'Create a hello world index.html' | claude -p --dangerously-skip-permissions`,
  { timeoutMs: 0 }
)

console.log(result.stdout)

sbx.kill()