kcimc commited on
Commit
daf5695
·
1 Parent(s): 99f97d6

add route to hide key

Browse files
README.md CHANGED
@@ -11,7 +11,7 @@ npm install
11
 
12
  2. Add your Gemini API key to `.env.local`:
13
  ```bash
14
- NEXT_PUBLIC_GEMINI_API_KEY=your_api_key_here
15
  ```
16
 
17
  3. Start the development server:
 
11
 
12
  2. Add your Gemini API key to `.env.local`:
13
  ```bash
14
+ GEMINI_API_KEY=your_api_key_here
15
  ```
16
 
17
  3. Start the development server:
src/app/api/generate/route.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+
3
+ const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
4
+
5
+ const generationConfig = {
6
+ temperature: 1,
7
+ topP: 0.95,
8
+ topK: 40,
9
+ maxOutputTokens: 8192,
10
+ responseMimeType: "text/plain",
11
+ };
12
+
13
+ export async function POST(request) {
14
+ try {
15
+ const { prompt, modelName, temperature } = await request.json();
16
+
17
+ const model = genAI.getGenerativeModel({
18
+ model: modelName,
19
+ systemInstruction: "Respond only with p5.js JavaScript code. Do not add any additional commentary before or after the code.",
20
+ });
21
+
22
+ const chatSession = model.startChat({
23
+ generationConfig: {
24
+ ...generationConfig,
25
+ temperature: parseFloat(temperature)
26
+ },
27
+ history: [
28
+ {
29
+ role: "user",
30
+ parts: [{ text: prompt }],
31
+ },
32
+ ],
33
+ });
34
+
35
+ const result = await chatSession.sendMessage(prompt);
36
+ let generatedCode = result.response.text();
37
+
38
+ if (generatedCode.includes('```')) {
39
+ generatedCode = generatedCode
40
+ .split('```')
41
+ .filter((block, index) => index % 2 === 1)
42
+ .join('\n')
43
+ .replace(/^javascript\n/m, '')
44
+ .trim();
45
+ }
46
+
47
+ return Response.json({ code: generatedCode });
48
+ } catch (error) {
49
+ console.error('Error generating code:', error);
50
+ return Response.json({ error: error.message }, { status: 500 });
51
+ }
52
+ }
src/app/globals.css CHANGED
@@ -53,3 +53,51 @@ iframe {
53
  border: none;
54
  background-color: white;
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  border: none;
54
  background-color: white;
55
  }
56
+
57
+ /* Bottom controls styling */
58
+ .bottom-controls {
59
+ backdrop-filter: blur(8px);
60
+ background-color: rgba(30, 30, 30, 0.95);
61
+ border: 1px solid rgba(75, 85, 99, 0.4);
62
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
63
+ }
64
+
65
+ /* Input and select styling */
66
+ .control-input {
67
+ background-color: rgba(31, 41, 55, 0.7) !important;
68
+ border: 1px solid rgba(75, 85, 99, 0.4) !important;
69
+ transition: all 0.2s ease;
70
+ }
71
+
72
+ .control-input:hover {
73
+ border-color: rgba(147, 197, 253, 0.4) !important;
74
+ }
75
+
76
+ .control-input:focus {
77
+ border-color: rgb(59, 130, 246) !important;
78
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
79
+ outline: none;
80
+ }
81
+
82
+ /* Button styling */
83
+ .control-button {
84
+ font-weight: 500;
85
+ transition: all 0.2s ease;
86
+ border: 1px solid transparent;
87
+ }
88
+
89
+ .control-button:hover {
90
+ transform: translateY(-1px);
91
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
92
+ }
93
+
94
+ .control-button:active {
95
+ transform: translateY(0);
96
+ }
97
+
98
+ .control-button.active {
99
+ background-color: rgb(59, 130, 246) !important;
100
+ border-color: rgb(37, 99, 235) !important;
101
+ }
102
+
103
+ /* Remove checkbox and label styling since we're not using them anymore */
src/components/Editor.js CHANGED
@@ -4,7 +4,6 @@ import { useRef, useState, useEffect, useCallback } from 'react';
4
  import dynamic from 'next/dynamic';
5
  import { javascript } from '@codemirror/lang-javascript';
6
  import { vscodeDark } from '@uiw/codemirror-theme-vscode';
7
- import { GoogleGenerativeAI } from "@google/generative-ai";
8
 
9
  // Dynamically import CodeMirror to avoid SSR issues
10
  const CodeMirror = dynamic(
@@ -21,16 +20,6 @@ function draw() {
21
  ellipse(mouseX, mouseY, 50, 50);
22
  }`;
23
 
24
- const genAI = new GoogleGenerativeAI(process.env.NEXT_PUBLIC_GEMINI_API_KEY);
25
-
26
- const generationConfig = {
27
- temperature: 1,
28
- topP: 0.95,
29
- topK: 40,
30
- maxOutputTokens: 8192,
31
- responseMimeType: "text/plain",
32
- };
33
-
34
  const getIframeContent = (userCode) => `
35
  <!DOCTYPE html>
36
  <html>
@@ -138,37 +127,25 @@ export default function Editor() {
138
 
139
  setIsGenerating(true);
140
  try {
141
- const model = genAI.getGenerativeModel({
142
- model: selectedModel,
143
- systemInstruction: "Respond only with p5.js JavaScript code. Do not add any additional commentary before or after the code.",
144
- });
145
-
146
- const chatSession = model.startChat({
147
- generationConfig: {
148
- ...generationConfig,
149
- temperature: parseFloat(temperature)
150
  },
151
- history: [
152
- {
153
- role: "user",
154
- parts: [{ text: prompt }],
155
- },
156
- ],
157
  });
158
 
159
- const result = await chatSession.sendMessage(prompt);
160
- let generatedCode = result.response.text();
161
 
162
- if (generatedCode.includes('```')) {
163
- generatedCode = generatedCode
164
- .split('```')
165
- .filter((block, index) => index % 2 === 1)
166
- .join('\n')
167
- .replace(/^javascript\n/m, '')
168
- .trim();
169
  }
170
 
171
- setCode(generatedCode);
172
 
173
  if (autoGenerate) {
174
  // Wait a moment to let the preview update before generating again
@@ -240,19 +217,19 @@ export default function Editor() {
240
  />
241
  </div>
242
  </div>
243
- <div className="absolute bottom-8 left-4 right-4 flex items-center gap-4 px-4 py-3 bg-[#1e1e1e] rounded-lg border border-gray-700 shadow-lg">
244
  <input
245
  type="text"
246
  value={prompt}
247
  onChange={(e) => setPrompt(e.target.value)}
248
  onKeyPress={handleKeyPress}
249
  placeholder="Write code for a clock using p5.js"
250
- className="flex-1 px-4 py-2 bg-gray-800 text-white rounded-md border border-gray-600"
251
  />
252
  <select
253
  value={selectedModel}
254
  onChange={(e) => setSelectedModel(e.target.value)}
255
- className="px-4 py-2 bg-gray-800 text-white rounded-md border border-gray-600"
256
  >
257
  <option value="gemini-2.0-flash">Gemini 2.0 Flash</option>
258
  <option value="gemini-2.0-pro-exp-02-05">Gemini 2.0 Pro</option>
@@ -266,52 +243,46 @@ export default function Editor() {
266
  step="0.1"
267
  value={temperature}
268
  onChange={(e) => setTemperature(e.target.value)}
269
- className="w-20 px-2 py-2 bg-gray-800 text-white rounded-md border border-gray-600"
270
  />
271
  </div>
272
- <div className="flex gap-2">
273
- <div className="flex items-center gap-2">
274
- <label className="text-white">
275
- <input
276
- type="checkbox"
277
- checked={autoSave}
278
- onChange={(e) => setAutoSave(e.target.checked)}
279
- className="mr-2"
280
- />
281
- Auto-save
282
- </label>
283
- </div>
284
  <button
285
  onClick={handleScreenshot}
286
- className="px-6 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
287
  >
288
  Save Screenshot
289
  </button>
290
  <button
291
  onClick={handleSaveCode}
292
- className="px-6 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 transition-colors"
293
  >
294
  Save Code
295
  </button>
296
- <div className="flex items-center gap-2">
297
- <label className="text-white">
298
- <input
299
- type="checkbox"
300
- checked={autoGenerate}
301
- onChange={(e) => setAutoGenerate(e.target.checked)}
302
- className="mr-2"
303
- />
304
- Auto-generate
305
- </label>
306
- </div>
307
  <button
308
  onClick={generateCode}
309
  disabled={isGenerating}
310
  className={`px-6 py-2 ${
311
  isGenerating
312
  ? 'bg-blue-400 cursor-not-allowed'
313
- : 'bg-blue-600 hover:bg-blue-700'
314
- } text-white rounded-md transition-colors`}
315
  >
316
  {isGenerating ? 'Generating...' : 'Generate'}
317
  </button>
 
4
  import dynamic from 'next/dynamic';
5
  import { javascript } from '@codemirror/lang-javascript';
6
  import { vscodeDark } from '@uiw/codemirror-theme-vscode';
 
7
 
8
  // Dynamically import CodeMirror to avoid SSR issues
9
  const CodeMirror = dynamic(
 
20
  ellipse(mouseX, mouseY, 50, 50);
21
  }`;
22
 
 
 
 
 
 
 
 
 
 
 
23
  const getIframeContent = (userCode) => `
24
  <!DOCTYPE html>
25
  <html>
 
127
 
128
  setIsGenerating(true);
129
  try {
130
+ const response = await fetch('/api/generate', {
131
+ method: 'POST',
132
+ headers: {
133
+ 'Content-Type': 'application/json',
 
 
 
 
 
134
  },
135
+ body: JSON.stringify({
136
+ prompt,
137
+ modelName: selectedModel,
138
+ temperature: parseFloat(temperature)
139
+ }),
 
140
  });
141
 
142
+ const data = await response.json();
 
143
 
144
+ if (data.error) {
145
+ throw new Error(data.error);
 
 
 
 
 
146
  }
147
 
148
+ setCode(data.code);
149
 
150
  if (autoGenerate) {
151
  // Wait a moment to let the preview update before generating again
 
217
  />
218
  </div>
219
  </div>
220
+ <div className="absolute bottom-8 left-4 right-4 flex items-center gap-6 px-6 py-4 bottom-controls">
221
  <input
222
  type="text"
223
  value={prompt}
224
  onChange={(e) => setPrompt(e.target.value)}
225
  onKeyPress={handleKeyPress}
226
  placeholder="Write code for a clock using p5.js"
227
+ className="flex-1 px-4 py-2 rounded-md control-input"
228
  />
229
  <select
230
  value={selectedModel}
231
  onChange={(e) => setSelectedModel(e.target.value)}
232
+ className="px-4 py-2 rounded-md control-input"
233
  >
234
  <option value="gemini-2.0-flash">Gemini 2.0 Flash</option>
235
  <option value="gemini-2.0-pro-exp-02-05">Gemini 2.0 Pro</option>
 
243
  step="0.1"
244
  value={temperature}
245
  onChange={(e) => setTemperature(e.target.value)}
246
+ className="w-20 px-2 py-2 rounded-md control-input"
247
  />
248
  </div>
249
+ <div className="flex items-center gap-4">
250
+ <button
251
+ onClick={() => setAutoSave(!autoSave)}
252
+ className={`px-4 py-2 ${
253
+ autoSave ? 'active' : 'bg-gray-600'
254
+ } text-white rounded-md control-button`}
255
+ >
256
+ Auto-save
257
+ </button>
 
 
 
258
  <button
259
  onClick={handleScreenshot}
260
+ className="px-4 py-2 bg-emerald-600 text-white rounded-md control-button"
261
  >
262
  Save Screenshot
263
  </button>
264
  <button
265
  onClick={handleSaveCode}
266
+ className="px-4 py-2 bg-purple-600 text-white rounded-md control-button"
267
  >
268
  Save Code
269
  </button>
270
+ <button
271
+ onClick={() => setAutoGenerate(!autoGenerate)}
272
+ className={`px-4 py-2 ${
273
+ autoGenerate ? 'active' : 'bg-gray-600'
274
+ } text-white rounded-md control-button`}
275
+ >
276
+ Auto-generate
277
+ </button>
 
 
 
278
  <button
279
  onClick={generateCode}
280
  disabled={isGenerating}
281
  className={`px-6 py-2 ${
282
  isGenerating
283
  ? 'bg-blue-400 cursor-not-allowed'
284
+ : 'bg-blue-600'
285
+ } text-white rounded-md control-button`}
286
  >
287
  {isGenerating ? 'Generating...' : 'Generate'}
288
  </button>