Overview
buntime.sh makes it easy to build and preview web applications. Every session gets a unique preview URL, and Bun 1.3’s built-in hot module reloading (HMR) automatically updates your app when code changes.Quick Start
Create a Simple Server
Copy
import { Buntime } from 'buntime.sh';
const client = new Buntime({ apiKey: process.env.BUNTIME_API_KEY });
// Create a session
const session = await client.sessions.create();
// Write a simple server
await client.files.write({
sessionId: session.id,
path: 'server.ts',
content: `
Bun.serve({
port: 8080,
fetch(req) {
return new Response("Hello from buntime!");
}
});
console.log("Server running on port 8080");
`
});
// Start the server
await client.execute({
sessionId: session.id,
command: 'bun run server.ts'
});
// Your app is live at:
console.log(`Preview URL: https://${session.id}.buntime.sh`);
Preview URLs
Every session gets a unique subdomain:Copy
https://{sessionId}.buntime.sh
- ✅ Always uses port 8080 (required)
- ✅ HTTPS enabled by default
- ✅ Proxied through Cloudflare for security
- ✅ Stays active as long as the session exists
- ✅ No configuration needed
Your web server must listen on port 8080. Other ports are not accessible via the preview URL.
Hot Module Reloading
Bun 1.3 includes built-in HMR that works automatically:Copy
// Write initial server
await client.files.write({
sessionId: session.id,
path: 'app.ts',
content: `
Bun.serve({
port: 8080,
fetch(req) {
return new Response("Version 1");
}
});
`
});
// Start the server
await client.execute({
sessionId: session.id,
command: 'bun --hot app.ts' // Enable hot reload
});
// Update the code - HMR automatically reloads!
await client.files.write({
sessionId: session.id,
path: 'app.ts',
content: `
Bun.serve({
port: 8080,
fetch(req) {
return new Response("Version 2 - Updated!");
}
});
`
});
// Visit preview URL - changes are live instantly
Use the
--hot flag when starting your server to enable automatic hot reloading.Static HTML
You can serve static HTML directly with Bun:Copy
await client.files.write({
sessionId: session.id,
path: 'index.html',
content: `
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<style>
body {
font-family: system-ui;
max-width: 800px;
margin: 50px auto;
padding: 20px;
}
</style>
</head>
<body>
<h1>Hello from buntime.sh!</h1>
<p>This is a static HTML page.</p>
</body>
</html>
`
});
await client.files.write({
sessionId: session.id,
path: 'server.ts',
content: `
Bun.serve({
port: 8080,
async fetch(req) {
const url = new URL(req.url);
const path = url.pathname === '/' ? '/index.html' : url.pathname;
try {
const file = Bun.file('.' + path);
return new Response(file);
} catch {
return new Response('Not Found', { status: 404 });
}
}
});
`
});
await client.execute({
sessionId: session.id,
command: 'bun --hot server.ts'
});
React Application
Build a full React app with JSX support:Copy
// Write React component
await client.files.write({
sessionId: session.id,
path: 'App.tsx',
content: `
import { useState } from 'react';
export function App() {
const [count, setCount] = useState(0);
return (
<div style={{ fontFamily: 'system-ui', padding: '50px' }}>
<h1>React + buntime.sh</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
`
});
// Write server with React rendering
await client.files.write({
sessionId: session.id,
path: 'server.tsx',
content: `
import { renderToReadableStream } from 'react-dom/server';
import { App } from './App';
Bun.serve({
port: 8080,
async fetch(req) {
const stream = await renderToReadableStream(<App />);
return new Response(stream, {
headers: { 'Content-Type': 'text/html' }
});
}
});
console.log('React app running on port 8080');
`
});
// Install React (Bun auto-installs on import, but explicit install is faster)
await client.execute({
sessionId: session.id,
command: 'bun add react react-dom'
});
// Start the server
await client.execute({
sessionId: session.id,
command: 'bun --hot server.tsx'
});
API Routes
Create a JSON API:Copy
await client.files.write({
sessionId: session.id,
path: 'api.ts',
content: `
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' }
];
Bun.serve({
port: 8080,
fetch(req) {
const url = new URL(req.url);
// GET /api/users
if (url.pathname === '/api/users' && req.method === 'GET') {
return Response.json(users);
}
// GET /api/users/:id
const userMatch = url.pathname.match(/^\/api\/users\/(\d+)$/);
if (userMatch && req.method === 'GET') {
const id = parseInt(userMatch[1]);
const user = users.find(u => u.id === id);
if (user) {
return Response.json(user);
}
return Response.json({ error: 'User not found' }, { status: 404 });
}
// POST /api/users
if (url.pathname === '/api/users' && req.method === 'POST') {
const body = await req.json();
const newUser = {
id: users.length + 1,
name: body.name,
email: body.email
};
users.push(newUser);
return Response.json(newUser, { status: 201 });
}
return Response.json({ error: 'Not found' }, { status: 404 });
}
});
console.log('API server running on port 8080');
`
});
await client.execute({
sessionId: session.id,
command: 'bun --hot api.ts'
});
WebSocket Server
Build real-time apps with WebSockets:Copy
await client.files.write({
sessionId: session.id,
path: 'websocket.ts',
content: `
const clients = new Set();
Bun.serve({
port: 8080,
fetch(req, server) {
const url = new URL(req.url);
// WebSocket upgrade
if (url.pathname === '/ws') {
const upgraded = server.upgrade(req);
if (!upgraded) {
return new Response('WebSocket upgrade failed', { status: 400 });
}
return undefined;
}
// Serve HTML client
return new Response(\`
<!DOCTYPE html>
<html>
<body>
<h1>WebSocket Chat</h1>
<div id="messages"></div>
<input id="input" type="text" placeholder="Type a message..." />
<button onclick="send()">Send</button>
<script>
const ws = new WebSocket('wss://' + location.host + '/ws');
const messages = document.getElementById('messages');
const input = document.getElementById('input');
ws.onmessage = (e) => {
const p = document.createElement('p');
p.textContent = e.data;
messages.appendChild(p);
};
function send() {
ws.send(input.value);
input.value = '';
}
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') send();
});
</script>
</body>
</html>
\`, {
headers: { 'Content-Type': 'text/html' }
});
},
websocket: {
open(ws) {
clients.add(ws);
console.log('Client connected. Total:', clients.size);
},
message(ws, message) {
// Broadcast to all clients
for (const client of clients) {
client.send(message);
}
},
close(ws) {
clients.delete(ws);
console.log('Client disconnected. Total:', clients.size);
}
}
});
console.log('WebSocket server running on port 8080');
`
});
await client.execute({
sessionId: session.id,
command: 'bun --hot websocket.ts'
});
File Uploads
Handle file uploads:Copy
await client.files.write({
sessionId: session.id,
path: 'upload.ts',
content: `
Bun.serve({
port: 8080,
async fetch(req) {
const url = new URL(req.url);
// Serve upload form
if (url.pathname === '/' && req.method === 'GET') {
return new Response(\`
<!DOCTYPE html>
<html>
<body>
<h1>File Upload</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" required />
<button type="submit">Upload</button>
</form>
</body>
</html>
\`, {
headers: { 'Content-Type': 'text/html' }
});
}
// Handle file upload
if (url.pathname === '/upload' && req.method === 'POST') {
const formData = await req.formData();
const file = formData.get('file') as File;
if (!file) {
return Response.json({ error: 'No file provided' }, { status: 400 });
}
// Save file
await Bun.write(\`uploads/\${file.name}\`, file);
return Response.json({
message: 'File uploaded successfully',
filename: file.name,
size: file.size,
type: file.type
});
}
return new Response('Not Found', { status: 404 });
}
});
console.log('Upload server running on port 8080');
`
});
// Create uploads directory
await client.execute({
sessionId: session.id,
command: 'mkdir -p uploads'
});
await client.execute({
sessionId: session.id,
command: 'bun --hot upload.ts'
});
Environment Variables
Pass secrets and config to your web app:Copy
await client.execute({
sessionId: session.id,
files: [
{
path: 'app.ts',
content: `
Bun.serve({
port: 8080,
fetch(req) {
return Response.json({
environment: process.env.NODE_ENV,
apiKey: process.env.API_KEY ? '***' : 'not set'
});
}
});
`
}
],
command: 'bun --hot app.ts',
env: {
NODE_ENV: 'production',
API_KEY: 'secret_key_123'
}
});
CORS Headers
Enable CORS for external API access:Copy
await client.files.write({
sessionId: session.id,
path: 'cors.ts',
content: `
Bun.serve({
port: 8080,
fetch(req) {
// Handle preflight
if (req.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
}
});
}
// Handle actual request
const data = { message: 'Hello from CORS-enabled API' };
return Response.json(data, {
headers: {
'Access-Control-Allow-Origin': '*'
}
});
}
});
`
});
Debugging Tips
Check if server is running
Check if server is running
List active processes to see if your server started:
Copy
const info = await client.sessions.info({ sessionId: session.id });
console.log('Active processes:', info.activeProcesses);
View server logs
View server logs
Execution output includes console.log from your server:
Copy
const result = await client.execute({
sessionId: session.id,
command: 'bun run server.ts'
});
console.log('Server output:', result.stdout);
console.log('Server errors:', result.stderr);
Test locally first
Test locally first
Test your server code locally before deploying:
Copy
bun run server.ts
# Visit http://localhost:8080
Restart the server
Restart the server
Kill the process and start fresh:
Copy
await client.execution.kill({ sessionId: session.id });
await client.execute({
sessionId: session.id,
command: 'bun --hot server.ts'
});
Limitations
Important limitations:
- Only port 8080 is accessible via preview URL
- Preview URLs require the session to be active
- No custom domains (use the provided subdomain)
- WebSocket connections close when session sleeps
- Maximum 1 web server per session
Best Practices
Use --hot flag
Enable hot reload for faster iteration during development
Handle errors
Return proper error responses with status codes
Log to stdout
Use console.log for debugging—output is captured in execute results
Test endpoints
Verify your API routes work before sharing preview URLs
Examples
Express Server
Full Express.js application
React SSR
Server-side rendered React app
REST API
Complete CRUD API example
WebSocket Chat
Real-time chat application