You have a Node.js app that needs to generate product descriptions in real time? A website that wants an AI assistant client-side without overloading the server? Google's Gemini API gives you access to advanced language models, but integrating it in JavaScript — both server-side and browser — has its quirks. At Meteora Web, we've been there: from API key management to handling streams. This guide shows you how.
How do you integrate Gemini API in a Node.js app?
On Node.js, the official @google/generative-ai library handles authentication and calls. Install it with npm, configure your API key, and start chatting. The problem? Many developers treat the API as a black box — we prefer to understand every request. Here's the basic setup.
Installation and API key configuration
npm install @google/generative-ai
Get your API key from Google AI Studio. Remember to protect it with environment variables, never hardcode it.
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
const result = await model.generateContent('Hello, who are you?');
console.log(result.response.text());
Note: the import works in ES Modules environment. If you use CommonJS, use require.
Sponsored Protocol
Error handling and retry
APIs have rate limits. We use a simple retry with backoff:
async function safeGenerate(prompt, retries = 3) {
try {
const result = await model.generateContent(prompt);
return result.response.text();
} catch (err) {
if (retries > 0 && err.status === 429) {
await new Promise(r => setTimeout(r, 2000));
return safeGenerate(prompt, retries - 1);
}
throw err;
}
}
How do you use Gemini API in the browser without exposing the secret key?
Never put the API key in the frontend. The solution? A Node.js proxy (or serverless) that acts as intermediary. Alternatively, you can use Firebase Auth + Google Cloud Endpoints for protected use cases. We prefer creating a simple Express endpoint.
Sponsored Protocol
Proxy server for the browser
// server.js (Node.js)
app.post('/api/gemini', async (req, res) => {
try {
const { prompt } = req.body;
const result = await safeGenerate(prompt);
res.json({ text: result });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
From the browser, a normal fetch:
const response = await fetch('/api/gemini', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: 'Explain relativity in one line' })
});
const data = await response.json();
console.log(data.text);
Never expose the key. A server in the middle is the minimum security.
How to handle streaming responses with Gemini API JavaScript?
Streaming responses improve UX: text appears word by word without waiting for completion. Gemini supports generateContentStream. In Node.js:
const stream = await model.generateContentStream(prompt);
for await (const chunk of stream.stream) {
process.stdout.write(chunk.text());
}
In the browser, via proxy with SSE (Server-Sent Events) or WebSocket. We recommend SSE for simplicity. Here's a server example:
Sponsored Protocol
// proxy with SSE
app.get('/api/gemini/stream', async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
const prompt = req.query.prompt;
const stream = await model.generateContentStream(prompt);
for await (const chunk of stream.stream) {
res.write(`data: ${JSON.stringify({ text: chunk.text() })}\n\n`);
}
res.end();
});
Client side, listen with EventSource:
const evtSource = new EventSource(`/api/gemini/stream?prompt=${encodeURIComponent('Tell a short story')}`);
evtSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data.text); // accumulate in a div
};
What are the differences between Gemini API integration in Node.js and the browser?
The @google/generative-ai library works both in Node.js and browser (with bundlers like Webpack or Vite), but attention: in the browser the key is exposed if you don't use a proxy. Also, native fetch support differs: on Node 18+ you can use fetch without a polyfill. In the browser, you need to handle CORS: if you call Google's API directly from the frontend, you need an authorized origin. We always avoid direct client calls for security.
Sponsored Protocol
Another difference: dependency management. On Node.js you install the npm package; on browser you load via CDN or bundle. Here's a CDN example:
<script type="module">
import { GoogleGenerativeAI } from 'https://cdn.jsdelivr.net/npm/@google/generative-ai/+esm';
// ... but then you must use a proxy to avoid exposing the key
</script>
How to optimize the cost of Gemini API calls in JavaScript?
Models have per-token pricing. We recommend: use smaller models (flash) for simple tasks, cache repeated responses with Redis or in-memory, and truncate long prompts. Example of caching in Node.js:
Sponsored Protocol
const cache = new Map();
async function generateWithCache(prompt) {
if (cache.has(prompt)) return cache.get(prompt);
const result = await generateContent(prompt);
cache.set(prompt, result);
setTimeout(() => cache.delete(prompt), 3600000); // expires after 1h
return result;
}
Always measure tokens with await model.countTokens(prompt) before calling.
What to do next
- Try the basic setup. Install the library, generate the first response. Then add error handling and retry.
- Create a proxy endpoint. For browser integrations, separate server and frontend. Never put the key in the client.
- Implement streaming if UX matters. Both in Node.js and via SSE for the browser.
- Monitor costs. Enable token counting and caching for repetitive use cases.
- Read the official documentation at Google Gemini API for models and parameters.
If you want to dive deeper into the Gemini ecosystem for developers, we have a comprehensive pillar guide covering the entire API.