Skip to content

Commit a557d21

Browse files
Juan Castañojuancastano
authored andcommitted
creating vite template & trying to get it to work
1 parent d6bfd64 commit a557d21

35 files changed

+4882
-2772
lines changed

app/api/generate/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export async function POST(request: NextRequest) {
2929
const validatedFiles = benchifyFileSchema.parse(generatedFiles);
3030

3131
// // Repair the generated code using Benchify's API
32-
const { repairedFiles, buildOutput } = await repairCode(validatedFiles);
32+
// const { repairedFiles, buildOutput } = await repairCode(validatedFiles);
3333

3434
const { sbxId, template, url } = await createSandbox({ files: generatedFiles });
3535

@@ -38,8 +38,8 @@ export async function POST(request: NextRequest) {
3838
// Return the results to the client
3939
return NextResponse.json({
4040
originalFiles: generatedFiles,
41-
repairedFiles: repairedFiles,
42-
buildOutput: buildOutput,
41+
// repairedFiles: repairedFiles,
42+
// buildOutput: buildOutput,
4343
previewUrl: url,
4444
});
4545
} catch (error) {

lib/e2b.ts

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,64 @@ if (!E2B_API_KEY) {
99
}
1010

1111
export async function createSandbox({ files }: { files: z.infer<typeof benchifyFileSchema> }) {
12-
const sandbox = await Sandbox.create('vue-dynamic-sandbox', { apiKey: E2B_API_KEY });
12+
const sandbox = await Sandbox.create('vite-template', { apiKey: E2B_API_KEY });
1313

14-
// Write all files to the sandbox at once
15-
await sandbox.files.write(
16-
files.map(file => ({
17-
path: `/home/user/app/${file.path}`,
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);
24+
}
25+
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}`,
1834
data: file.content
19-
}))
20-
);
35+
}));
36+
37+
// Write all files to the sandbox EXCEPT package.json
38+
await sandbox.files.write(filesToWrite);
2139

2240
console.log("sandbox created", sandbox.sandboxId);
2341

24-
// Find package.json to check for new dependencies
25-
const packageJsonFile = files.find(file => file.path === 'package.json');
26-
if (packageJsonFile) {
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);
55+
}
56+
57+
// Process dependencies if AI provided a package.json
58+
if (aiPackageJsonFile) {
2759
try {
28-
const packageJson = JSON.parse(packageJsonFile.content);
29-
const dependencies = packageJson.dependencies || {};
30-
const devDependencies = packageJson.devDependencies || {};
60+
const aiPackageJson = JSON.parse(aiPackageJsonFile.content);
61+
const dependencies = aiPackageJson.dependencies || {};
62+
const devDependencies = aiPackageJson.devDependencies || {};
3163

32-
// Filter out pre-installed dependencies (vue, tailwindcss, etc.)
33-
const preInstalled = ['vue', 'tailwindcss', 'autoprefixer', 'postcss', 'vite', '@vitejs/plugin-vue', '@vue/compiler-sfc'];
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+
];
3470

3571
// Get new deps that need to be installed
3672
const newDeps = Object.keys(dependencies).filter(dep => !preInstalled.includes(dep));
@@ -39,29 +75,40 @@ export async function createSandbox({ files }: { files: z.infer<typeof benchifyF
3975
// Install only new dependencies if any exist
4076
if (newDeps.length > 0) {
4177
console.log("Installing new dependencies:", newDeps.join(", "));
42-
await sandbox.commands.run(`cd /home/user/app && npm install --legacy-peer-deps ${newDeps.join(' ')}`);
78+
await sandbox.commands.run(`cd /app && npm install --legacy-peer-deps ${newDeps.join(' ')}`);
4379
}
4480

4581
if (newDevDeps.length > 0) {
4682
console.log("Installing new dev dependencies:", newDevDeps.join(", "));
47-
await sandbox.commands.run(`cd /home/user/app && npm install --legacy-peer-deps --save-dev ${newDevDeps.join(' ')}`);
83+
await sandbox.commands.run(`cd /app && npm install --legacy-peer-deps --save-dev ${newDevDeps.join(' ')}`);
4884
}
4985
} catch (error) {
5086
console.error("Error parsing package.json:", error);
5187
}
5288
}
5389

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+
}
98+
5499
// Run the Vite app
55-
sandbox.commands.run('npx vite --host', {
56-
cwd: '/home/user/app',
57-
timeoutMs: 0,
58-
}).catch((error) => {
100+
try {
101+
await sandbox.commands.run('npm run dev -- --host', {
102+
cwd: '/app',
103+
timeoutMs: 0,
104+
});
105+
} catch (error) {
59106
console.error("Error running Vite:", error);
60-
});
107+
}
61108

62109
return {
63110
sbxId: sandbox.sandboxId,
64-
template: 'vue-dynamic-sandbox',
111+
template: 'vite-template',
65112
url: `https://${sandbox.getHost(5173)}`
66113
};
67114
}

lib/openai.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { streamObject } from 'ai';
33
import { openai } from '@ai-sdk/openai';
44
import { z } from 'zod';
5-
import { VUE_APP_SYSTEM_PROMPT, VUE_APP_USER_PROMPT, TEMPERATURE, MODEL } from './prompts';
5+
import { REACT_APP_SYSTEM_PROMPT, REACT_APP_USER_PROMPT, TEMPERATURE, MODEL } from './prompts';
66

77
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
88

@@ -29,8 +29,8 @@ export async function generateApp(
2929
schema: fileSchema,
3030
temperature: TEMPERATURE,
3131
messages: [
32-
{ role: 'system', content: VUE_APP_SYSTEM_PROMPT },
33-
{ role: 'user', content: VUE_APP_USER_PROMPT(description) }
32+
{ role: 'system', content: REACT_APP_SYSTEM_PROMPT },
33+
{ role: 'user', content: REACT_APP_USER_PROMPT(description) }
3434
]
3535
});
3636

lib/prompts.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
// lib/prompts.ts
22

3-
export const VUE_APP_SYSTEM_PROMPT = `You are an expert Vue.js and Tailwind CSS developer.
4-
You will be generating a complete Vue 3 application based on the provided description.
3+
export const REACT_APP_SYSTEM_PROMPT = `You are an expert React, TypeScript, and Tailwind CSS developer.
4+
You will be generating React application code based on the provided description.
5+
This code will be inserted into an existing Vite + React + TypeScript template.
6+
57
Follow these guidelines:
6-
- Use Vue 3 Composition API with <script setup> syntax
7-
- Use Tailwind CSS for styling
8-
- Include the package.json file in the response
9-
- The following files are provided and should not be modified: nuxt.config.ts, postcss.config.ts, tailwind.config.ts, vite.config.ts
10-
- Follow Vue.js best practices and conventions
8+
- Use React 19 with TypeScript
9+
- Use Tailwind CSS v4 for styling
10+
- DO NOT use component libraries like shadcn/ui or Material UI
11+
- Build all UI components from scratch using Tailwind CSS
12+
- Use the hooks pattern and follow React best practices
1113
- Create a well-structured application with proper component organization
12-
- Include proper TypeScript types
14+
- Ensure proper TypeScript typing
1315
- Add comments explaining complex logic
1416
- Handle loading states and errors appropriately
1517
- Ensure responsive design
16-
- Use port 5173 for the Vite server
17-
- Always remember to write an index.css file and import it in the main app file
18+
- Import CSS in main.tsx as: import './index.css'
19+
- Use relative imports (not path aliases): import App from './App.tsx'
20+
- IMPORTANT: Always generate ALL components that you reference or import
21+
22+
IMPORTANT: Only generate these application files:
23+
- src/main.tsx (entry point)
24+
- src/App.tsx (main app component)
25+
- src/index.css (with Tailwind imports)
26+
- src/components/* (your React components)
27+
- package.json (only for additional dependencies you need)
28+
29+
DO NOT generate configuration files like:
30+
- vite.config.ts
31+
- tsconfig files
32+
- eslint configs
33+
- index.html
34+
35+
These configuration files are already part of the template.
1836
1937
RESPONSE FORMAT:
2038
You must return a valid JSON array of file objects. Each file object must have exactly this structure:
@@ -25,8 +43,8 @@ You must return a valid JSON array of file objects. Each file object must have e
2543
2644
Do not include any markdown formatting, code blocks, or explanatory text. The response must be pure JSON.`;
2745

28-
export const VUE_APP_USER_PROMPT = (description: string) => `
29-
Create a Vue.js application with the following requirements:
46+
export const REACT_APP_USER_PROMPT = (description: string) => `
47+
Create a React application with the following requirements:
3048
${description}`;
3149

3250
export const TEMPERATURE = 0.7;

templates/.DS_Store

6 KB
Binary file not shown.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# You can use most Debian-based base images
2+
FROM ubuntu:22.04
3+
4+
# Install dependencies and customize sandbox
5+
ENV DEBIAN_FRONTEND=noninteractive
6+
RUN apt-get update && apt-get install -y \
7+
curl \
8+
git \
9+
bash \
10+
ca-certificates \
11+
gnupg \
12+
build-essential \
13+
sudo \
14+
&& apt-get clean \
15+
&& rm -rf /var/lib/apt/lists/*
16+
17+
# Install Node.js 18.x LTS (more stable for this purpose)
18+
RUN mkdir -p /etc/apt/keyrings && \
19+
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
20+
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
21+
apt-get update && \
22+
apt-get install -y nodejs && \
23+
npm install -g [email protected]
24+
25+
# Create app user
26+
RUN useradd -m -s /bin/bash viteuser && \
27+
echo "viteuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/viteuser
28+
29+
# Create app directory
30+
WORKDIR /app
31+
32+
# Install Vite globally
33+
RUN npm install -g vite create-vite
34+
35+
# Create basic Vite project structure
36+
COPY ./template /app
37+
38+
# Set proper ownership and permissions
39+
RUN chown -R viteuser:viteuser /app && \
40+
chmod -R 775 /app
41+
42+
# Install dependencies as the viteuser
43+
USER viteuser
44+
RUN cd /app && npm install
45+
46+
# Create Vite cache directories with proper permissions
47+
RUN mkdir -p /app/node_modules/.vite && \
48+
mkdir -p /app/node_modules/.vite-temp && \
49+
chmod -R 777 /app/node_modules/.vite && \
50+
chmod -R 777 /app/node_modules/.vite-temp
51+
52+
# Expose port
53+
EXPOSE 5173
54+
55+
# Set entrypoint
56+
CMD ["npm", "run", "dev"]

templates/vite-template/e2b.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# This is a config for E2B sandbox template.
2+
# You can use template ID (0szqhsrgikxynzgu09xv) or template name (vite-template) to create a sandbox:
3+
4+
# Python SDK
5+
# from e2b import Sandbox, AsyncSandbox
6+
# sandbox = Sandbox("vite-template") # Sync sandbox
7+
# sandbox = await AsyncSandbox.create("vite-template") # Async sandbox
8+
9+
# JS SDK
10+
# import { Sandbox } from 'e2b'
11+
# const sandbox = await Sandbox.create('vite-template')
12+
13+
team_id = "35f2ed91-a6af-4e6c-a693-9e9e244fcdbd"
14+
dockerfile = "e2b.Dockerfile"
15+
template_name = "vite-template"
16+
template_id = "0szqhsrgikxynzgu09xv"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# React + TypeScript + Vite
2+
3+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4+
5+
Currently, two official plugins are available:
6+
7+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
8+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9+
10+
## Expanding the ESLint configuration
11+
12+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
13+
14+
```js
15+
export default tseslint.config({
16+
extends: [
17+
// Remove ...tseslint.configs.recommended and replace with this
18+
...tseslint.configs.recommendedTypeChecked,
19+
// Alternatively, use this for stricter rules
20+
...tseslint.configs.strictTypeChecked,
21+
// Optionally, add this for stylistic rules
22+
...tseslint.configs.stylisticTypeChecked,
23+
],
24+
languageOptions: {
25+
// other options...
26+
parserOptions: {
27+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
28+
tsconfigRootDir: import.meta.dirname,
29+
},
30+
},
31+
})
32+
```
33+
34+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
35+
36+
```js
37+
// eslint.config.js
38+
import reactX from 'eslint-plugin-react-x'
39+
import reactDom from 'eslint-plugin-react-dom'
40+
41+
export default tseslint.config({
42+
plugins: {
43+
// Add the react-x and react-dom plugins
44+
'react-x': reactX,
45+
'react-dom': reactDom,
46+
},
47+
rules: {
48+
// other rules...
49+
// Enable its recommended typescript rules
50+
...reactX.configs['recommended-typescript'].rules,
51+
...reactDom.configs.recommended.rules,
52+
},
53+
})
54+
```

0 commit comments

Comments
 (0)