
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@shopkit/sandbox
Advanced tools
TypeScript client for BoxLite sandbox - live code preview with Vite dev server
TypeScript client for BoxLite sandbox - live code preview with Vite dev server.
This package provides a TypeScript client for the BoxLite sandbox backend. It enables:
bun add @shopkit/sandbox
The BoxLite backend must be running:
# Clone the perfect-web-clone repository
git clone https://github.com/ericshang98/perfect-web-clone
cd perfect-web-clone
# Install dependencies
pip install -r backend/requirements.txt
playwright install chromium
# Start the backend
python backend/main.py
# Server runs on http://localhost:5100
import { BoxLiteClient } from '@shopkit/sandbox';
const client = new BoxLiteClient({
baseUrl: 'http://localhost:5100'
});
// Create a sandbox
const sandbox = await client.createSandbox();
console.log('Sandbox ID:', sandbox.sandboxId);
// Write files
await client.writeFile('/src/App.tsx', `
export default function App() {
return <div className="p-4">Hello World</div>;
}
`);
// Start dev server
await client.startDevServer();
console.log('Preview URL:', sandbox.previewUrl); // http://localhost:8080
// Get screenshot for AI review
const screenshot = await client.getScreenshot();
console.log('Screenshot (base64):', screenshot?.substring(0, 50));
// Check for build errors
const errors = await client.getBuildErrors();
if (errors.length > 0) {
console.log('Build errors:', errors);
}
import { SandboxManager } from '@shopkit/sandbox';
const manager = new SandboxManager({
baseUrl: 'http://localhost:5100'
});
// Initialize sandbox
await manager.initialize();
// Connect to agent WebSocket
manager.connectAgentWebSocket({
onStateUpdate: (state) => {
console.log('Sandbox state:', state.status);
console.log('Preview URL:', state.preview_url);
},
onTextDelta: (delta) => {
// Stream AI response
process.stdout.write(delta);
},
onToolCall: (tool) => {
console.log('AI executing tool:', tool.name);
},
onToolResult: (result) => {
console.log('Tool result:', result.success ? 'Success' : 'Failed');
},
onError: (error) => {
console.error('Error:', error);
},
onDone: () => {
console.log('AI finished');
}
});
// Send a message to the AI agent
manager.sendChatMessage('Create a product card component with hover effects');
// Write files directly
await manager.writeFiles({
'/src/components/ProductCard.tsx': productCardCode,
'/src/styles/card.css': cardStyles
});
// Get preview screenshot
const screenshot = await manager.getScreenshot();
// Clean up
await manager.destroy();
import { useEffect, useState } from 'react';
import { SandboxManager, SandboxState } from '@shopkit/sandbox';
function usePreview(code: string) {
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const [manager] = useState(() => new SandboxManager());
useEffect(() => {
let mounted = true;
async function setup() {
try {
await manager.initialize();
await manager.writeFile('/src/App.tsx', code);
const result = await manager.startDevServer();
if (mounted && result.success) {
setPreviewUrl(result.preview_url || 'http://localhost:8080');
}
} catch (e) {
if (mounted) setError(e.message);
}
}
setup();
return () => {
mounted = false;
manager.destroy();
};
}, [code]);
return { previewUrl, error };
}
| Method | Description |
|---|---|
createSandbox(id?) | Create a new sandbox |
reconnectSandbox(id) | Reconnect to existing sandbox |
getSandboxState(id?) | Get current sandbox state |
deleteSandbox(id?) | Delete a sandbox |
writeFile(path, content, id?) | Write a file |
writeFiles(files, id?) | Write multiple files |
readFile(path, id?) | Read a file |
listFiles(path?, id?) | List directory contents |
runCommand(cmd, opts?, id?) | Run shell command |
startDevServer(id?) | Start Vite dev server |
stopDevServer(id?) | Stop dev server |
getVisualSummary(id?) | Get visual summary with screenshot |
getScreenshot(id?) | Get screenshot as base64 |
getBuildErrors(source?, id?) | Get build/runtime errors |
Extends BoxLiteClient with WebSocket management and event handling.
| Method | Description |
|---|---|
initialize(id?) | Initialize new sandbox |
reconnect(id) | Reconnect to sandbox |
destroy() | Clean up sandbox |
connectWebSocket(handlers?) | Connect for real-time updates |
connectAgentWebSocket(handlers?) | Connect for AI interactions |
sendChatMessage(msg, sourceId?) | Send message to AI agent |
setEventHandlers(handlers) | Set event callbacks |
interface SandboxEventHandlers {
onStateUpdate?: (state: SandboxState) => void;
onTerminalOutput?: (data: { terminal_id: string; data: string }) => void;
onTextDelta?: (delta: string) => void;
onText?: (content: string) => void;
onToolCall?: (data: { id: string; name: string; input: object }) => void;
onToolResult?: (data: { id: string; success: boolean; result: string }) => void;
onError?: (error: string) => void;
onDone?: () => void;
onConnect?: () => void;
onDisconnect?: () => void;
}
| Variable | Default | Description |
|---|---|---|
BOXLITE_URL | http://localhost:5100 | BoxLite server URL (server-side) |
NEXT_PUBLIC_BOXLITE_URL | http://localhost:5100 | BoxLite server URL (client-side) |
| Variable | Default | Description |
|---|---|---|
PORT | 5100 | BoxLite server port |
BOXLITE_DEV_PORT | 8080 | Vite dev server port |
BOXLITE_SANDBOX_DIR | /tmp/boxlite-sandboxes | Sandbox directory |
BOXLITE_SINGLETON_MODE | true | Reuse single sandbox |
ANTHROPIC_API_KEY | - | API key for AI features |
LOG_LEVEL | INFO | Logging level |
For production use, the BoxLite backend must be deployed as a separate service:
┌──────────────────┐ ┌──────────────────────────┐
│ Admin App │ │ BoxLite Backend │
│ (Next.js) │◄────►│ (Python/FastAPI) │
│ Vercel/Railway │ REST │ Railway/Render/Docker │
│ │ + │ │
│ │ WS │ │
└──────────────────┘ └──────────────────────────┘
Clone BoxLite backend:
git clone https://github.com/ericshang98/perfect-web-clone
cd perfect-web-clone/backend
Deploy to Railway:
railway init
railway up
Set environment variables in Railway dashboard
Configure admin app:
NEXT_PUBLIC_BOXLITE_URL=https://your-boxlite.up.railway.app
See BoxLite Production Deployment Guide for detailed Docker, Railway, Render, and AWS/GCP deployment instructions.
MIT
FAQs
TypeScript client for BoxLite sandbox - live code preview with Vite dev server
We found that @shopkit/sandbox demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.