Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Gemini API Key for local development/testing
# Note: For the GitHub Pages site, users will be prompted to enter their own API key
# which is stored in their browser's localStorage (not shared with the server)
# Get your free API key at: https://aistudio.google.com/apikey
GEMINI_API_KEY=AIzaSyB1kLWIDXGvwikSQyAbqhytf3wHf65aulQ
Comment thread
deaneeth marked this conversation as resolved.
Empty file added docs/.nojekyll
Empty file.
120 changes: 120 additions & 0 deletions docs/cloudflare-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* TinyGPU Gemini API Proxy - Cloudflare Worker
*
* This worker proxies requests to the Gemini API, keeping your API key secure.
* Deploy this to Cloudflare Workers and set the GEMINI_API_KEY secret.
*
* Setup Instructions:
* 1. Go to https://dash.cloudflare.com/ and sign up/login
* 2. Go to Workers & Pages > Create Application > Create Worker
* 3. Name it something like "tinygpu-gemini-proxy"
* 4. Replace the default code with this file's contents
* 5. Go to Settings > Variables > Add Variable
* - Name: GEMINI_API_KEY
* - Value: Your Gemini API key
* - Click "Encrypt" to keep it secret
* 6. Save and Deploy
* 7. Your worker URL will be: https://tinygpu-gemini-proxy.<your-subdomain>.workers.dev
*/

export default {
async fetch(request, env) {
// Handle CORS preflight
if (request.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
Comment thread
deaneeth marked this conversation as resolved.
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Max-Age": "86400",
},
});
}

// Only allow POST requests
if (request.method !== "POST") {
return new Response(JSON.stringify({ error: "Method not allowed" }), {
status: 405,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
Comment thread
deaneeth marked this conversation as resolved.
},
});
}

try {
// Get the request body
const body = await request.json();

// Validate required fields
if (!body.prompt) {
return new Response(JSON.stringify({ error: "Missing prompt" }), {
status: 400,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
}
Comment thread
deaneeth marked this conversation as resolved.

// Build Gemini API request
const geminiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${env.GEMINI_API_KEY}`;
Comment thread
deaneeth marked this conversation as resolved.

const geminiPayload = {
contents: [{ parts: [{ text: body.prompt }] }],
};

// Add system instruction if provided
if (body.systemPrompt) {
geminiPayload.systemInstruction = {
parts: [{ text: body.systemPrompt }],
};
}

// Call Gemini API
const geminiResponse = await fetch(geminiUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(geminiPayload),
});

if (!geminiResponse.ok) {
const errorText = await geminiResponse.text();
return new Response(
JSON.stringify({
error: "Gemini API error",
status: geminiResponse.status,
details: errorText,
}),
{
status: geminiResponse.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
}
);
Comment thread
deaneeth marked this conversation as resolved.
}

const data = await geminiResponse.json();
const text =
data.candidates?.[0]?.content?.parts?.[0]?.text ||
"No response generated.";

return new Response(JSON.stringify({ text }), {
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
}
},
};
Loading