Skip to content

Commit 2791bad

Browse files
authored
Finally got a template that works BEN-783 (#15)
2 parents 638766e + 925c778 commit 2791bad

27 files changed

+110
-4868
lines changed

lib/e2b.ts

Lines changed: 29 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -9,107 +9,44 @@ if (!E2B_API_KEY) {
99
}
1010

1111
export async function createSandbox({ files }: { files: z.infer<typeof benchifyFileSchema> }) {
12-
const sandbox = await Sandbox.create('vite-template', { apiKey: E2B_API_KEY });
13-
14-
// Debug: Log template files before writing anything
15-
try {
16-
console.log("TEMPLATE VERIFICATION:");
17-
const { stdout: templateFiles } = await sandbox.commands.run('ls -la /app', { cwd: '/app' });
18-
console.log("Template files in /app:", templateFiles);
19-
20-
const { stdout: templatePkgJson } = await sandbox.commands.run('cat /app/package.json', { cwd: '/app' });
21-
console.log("Template package.json:", templatePkgJson);
22-
} catch (error) {
23-
console.error("Error checking template:", error);
12+
// Create sandbox from the improved template
13+
const sandbox = await Sandbox.create('vite-support', { apiKey: E2B_API_KEY });
14+
console.log(`Sandbox created: ${sandbox.sandboxId}`);
15+
16+
// Check if the user provided CSS files with old Tailwind syntax
17+
const cssFiles = files.filter(file => file.path.endsWith('.css'));
18+
for (const cssFile of cssFiles) {
19+
// If the file contains @tailwind directives, replace with the new v4 syntax
20+
if (cssFile.content.includes('@tailwind')) {
21+
console.log(`Updating Tailwind v4 syntax in ${cssFile.path}`);
22+
cssFile.content = '@import "tailwindcss";';
23+
}
2424
}
2525

26-
// Find AI-generated package.json to extract dependencies
27-
const aiPackageJsonFile = files.find(file => file.path === 'package.json');
28-
29-
// Filter out package.json from files to write (we'll handle it separately)
30-
const filesToWrite = files
31-
.filter(file => file.path !== 'package.json')
32-
.map(file => ({
33-
path: `/app/${file.path}`,
34-
data: file.content
35-
}));
36-
37-
// Write all files to the sandbox EXCEPT package.json
38-
await sandbox.files.write(filesToWrite);
39-
40-
console.log("sandbox created", sandbox.sandboxId);
41-
42-
// Debug: Verify files after writing
43-
try {
44-
console.log("AFTER WRITING FILES:");
45-
const { stdout: rootContents } = await sandbox.commands.run('ls -la /app', { cwd: '/app' });
46-
console.log("Files in /app:", rootContents);
47-
48-
const { stdout: packageJson } = await sandbox.commands.run('cat /app/package.json', { cwd: '/app' });
49-
console.log("Current package.json:", packageJson);
50-
51-
const { stdout: scriptsList } = await sandbox.commands.run('npm run', { cwd: '/app' });
52-
console.log("Available npm scripts:", scriptsList);
53-
} catch (error) {
54-
console.error("Error in debug commands:", error);
26+
// Check if the user provided a postcss.config.js and if it needs to be updated for Tailwind v4
27+
const postcssFile = files.find(file => file.path === 'postcss.config.js');
28+
if (postcssFile && postcssFile.content.includes('tailwindcss')) {
29+
// Fix postcss config to use @tailwindcss/postcss
30+
const fixedContent = postcssFile.content.replace(/['"]tailwindcss['"]/, '"@tailwindcss/postcss"');
31+
// Update the file with fixed content
32+
postcssFile.content = fixedContent;
5533
}
5634

57-
// Process dependencies if AI provided a package.json
58-
if (aiPackageJsonFile) {
59-
try {
60-
const aiPackageJson = JSON.parse(aiPackageJsonFile.content);
61-
const dependencies = aiPackageJson.dependencies || {};
62-
const devDependencies = aiPackageJson.devDependencies || {};
35+
// Write files directly to the working directory (/app)
36+
const filesToWrite = files.map(file => ({
37+
path: `/app/${file.path}`,
38+
data: file.content
39+
}));
6340

64-
// Filter out pre-installed dependencies
65-
const preInstalled = [
66-
'react', 'react-dom', '@tailwindcss/vite', 'tailwindcss',
67-
'@types/react', '@types/react-dom', '@vitejs/plugin-react',
68-
'typescript', 'vite', 'postcss', 'autoprefixer'
69-
];
70-
71-
// Get new deps that need to be installed
72-
const newDeps = Object.keys(dependencies).filter(dep => !preInstalled.includes(dep));
73-
const newDevDeps = Object.keys(devDependencies).filter(dep => !preInstalled.includes(dep));
74-
75-
// Install only new dependencies if any exist
76-
if (newDeps.length > 0) {
77-
console.log("Installing new dependencies:", newDeps.join(", "));
78-
await sandbox.commands.run(`cd /app && npm install --legacy-peer-deps ${newDeps.join(' ')}`);
79-
}
80-
81-
if (newDevDeps.length > 0) {
82-
console.log("Installing new dev dependencies:", newDevDeps.join(", "));
83-
await sandbox.commands.run(`cd /app && npm install --legacy-peer-deps --save-dev ${newDevDeps.join(' ')}`);
84-
}
85-
} catch (error) {
86-
console.error("Error parsing package.json:", error);
87-
}
88-
}
89-
90-
// Fix permissions with sudo before starting
91-
try {
92-
await sandbox.commands.run('sudo rm -rf /app/node_modules/.vite', { cwd: '/app' });
93-
await sandbox.commands.run('sudo mkdir -p /app/node_modules/.vite', { cwd: '/app' });
94-
await sandbox.commands.run('sudo chmod -R 777 /app/node_modules/.vite', { cwd: '/app' });
95-
} catch (error) {
96-
console.error("Error fixing permissions:", error);
97-
}
41+
await sandbox.files.write(filesToWrite);
9842

99-
// Run the Vite app
100-
try {
101-
await sandbox.commands.run('npm run dev -- --host', {
102-
cwd: '/app',
103-
timeoutMs: 0,
104-
});
105-
} catch (error) {
106-
console.error("Error running Vite:", error);
107-
}
43+
const previewUrl = `https://${sandbox.getHost(5173)}`;
44+
console.log('Preview URL: ', previewUrl);
10845

10946
return {
11047
sbxId: sandbox.sandboxId,
111-
template: 'vite-template',
112-
url: `https://${sandbox.getHost(5173)}`
48+
template: 'vite-support',
49+
url: previewUrl
11350
};
11451
}
11552

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {
6-
"dev": "next dev --turbopack",
6+
"dev": "next dev --port 5173",
77
"build": "next build",
88
"start": "next start",
99
"lint": "next lint"
@@ -43,4 +43,4 @@
4343
"tw-animate-css": "^1.2.9",
4444
"typescript": "^5"
4545
}
46-
}
46+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
# This script runs during building the sandbox template
4+
# and makes sure the Vite app is (1) running and (2) accessible
5+
function ping_server() {
6+
counter=0
7+
response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:5173")
8+
while [[ ${response} -ne 200 ]]; do
9+
let counter++
10+
if (( counter % 20 == 0 )); then
11+
echo "Waiting for Vite dev server to start..."
12+
sleep 0.1
13+
fi
14+
15+
response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:5173")
16+
done
17+
}
18+
19+
# Start the Vite dev server
20+
ping_server &
21+
cd /home/user && npm run dev

templates/vite-support/e2b.Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Simpler Dockerfile
2+
FROM node:21-slim
3+
4+
# Install necessary tools
5+
RUN apt-get update && apt-get install -y bash curl && rm -rf /var/lib/apt/lists/*
6+
7+
# Set working directory directly
8+
WORKDIR /app
9+
10+
# Set up Vite with React + TypeScript
11+
RUN npm create vite@latest . -- --template react-ts
12+
13+
# Install all dependencies
14+
RUN npm install
15+
16+
# Install Tailwind CSS with Vite plugin (v4 approach)
17+
RUN npm install -D tailwindcss @tailwindcss/vite
18+
19+
# Update vite.config.ts to use the Tailwind plugin and include allowedHosts
20+
RUN echo 'import { defineConfig } from "vite"\nimport react from "@vitejs/plugin-react"\nimport tailwindcss from "@tailwindcss/vite"\n\nexport default defineConfig({\n plugins: [\n react(),\n tailwindcss(),\n ],\n server: {\n host: true,\n allowedHosts: [".e2b.app"],\n },\n})' > vite.config.ts
21+
22+
# Configure Tailwind CSS (simplified import for v4)
23+
RUN echo '@import "tailwindcss";' > ./src/index.css
24+
25+
# Make directory writable (this is crucial)
26+
RUN chmod -R 777 /app
27+
28+
# Set proper entrypoint
29+
ENTRYPOINT ["bash", "-c", "cd /app && npm run dev -- --host --port 5173"]

templates/vite-support/e2b.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This is a config for E2B sandbox template.
2+
# You can use template ID (5harom00c0l7yk46ewmn) or template name (vite-support) to create a sandbox:
3+
4+
# Python SDK
5+
# from e2b import Sandbox, AsyncSandbox
6+
# sandbox = Sandbox("vite-support") # Sync sandbox
7+
# sandbox = await AsyncSandbox.create("vite-support") # Async sandbox
8+
9+
# JS SDK
10+
# import { Sandbox } from 'e2b'
11+
# const sandbox = await Sandbox.create('vite-support')
12+
13+
team_id = "35f2ed91-a6af-4e6c-a693-9e9e244fcdbd"
14+
memory_mb = 1_024
15+
start_cmd = "cd /app && npm run dev -- --host --port 5173"
16+
dockerfile = "e2b.Dockerfile"
17+
template_name = "vite-support"
18+
template_id = "5harom00c0l7yk46ewmn"

templates/vite-support/vite.config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defineConfig } from "vite";
2+
import react from "@vitejs/plugin-react";
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [react()],
7+
server: {
8+
host: true,
9+
allowedHosts: [".e2b.app"],
10+
},
11+
});

templates/vite-template/e2b.Dockerfile

Lines changed: 0 additions & 56 deletions
This file was deleted.

templates/vite-template/e2b.toml

Lines changed: 0 additions & 16 deletions
This file was deleted.

templates/vite-template/template/.gitignore

Lines changed: 0 additions & 24 deletions
This file was deleted.

templates/vite-template/template/README.md

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)