> ## Documentation Index
> Fetch the complete documentation index at: https://docs.geko.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Use it in your app

> Server-side integration for Next.js and Express — the safe way.

The golden rule: **call Geko from your server, and let your frontend call your server.** The API now allows cross-origin browser calls (CORS), but that doesn't make it safe to expose your key — a key shipped to the client is public. Keep it on the server.

```
browser ──▶ your backend (holds GEKO_API_KEY) ──▶ Geko API
```

## Next.js (App Router)

A route handler that proxies synthesis. The key never leaves the server.

```ts app/api/tts/route.ts theme={null}
import { Geko, GekoError } from "@gekoai/sdk";

const geko = new Geko({ apiKey: process.env.GEKO_API_KEY });

// cold starts can be slow — give the function room (Vercel: see maxDuration limits)
export const maxDuration = 120;

export async function POST(req: Request) {
  const { text, voice } = await req.json();
  if (!text?.trim()) {
    return Response.json({ error: "text is required" }, { status: 400 });
  }
  try {
    const audio = await geko.tts.create({ text, voice });
    return new Response(audio, {
      headers: { "content-type": "audio/wav", "cache-control": "no-store" },
    });
  } catch (err) {
    if (err instanceof GekoError) {
      return Response.json({ error: err.detail }, { status: err.status || 502 });
    }
    return Response.json({ error: "synthesis failed" }, { status: 502 });
  }
}
```

Call it from a client component:

```ts theme={null}
async function speak(text: string, voice = "Aigerim") {
  const res = await fetch("/api/tts", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ text, voice }),
  });
  if (!res.ok) throw new Error((await res.json()).error);
  const bytes = await res.arrayBuffer();
  new Audio(URL.createObjectURL(new Blob([bytes], { type: "audio/wav" }))).play();
}
```

## Express

```ts theme={null}
import express from "express";
import { Geko, GekoError } from "@gekoai/sdk";

const app = express();
app.use(express.json());
const geko = new Geko({ apiKey: process.env.GEKO_API_KEY });

app.post("/tts", async (req, res) => {
  try {
    const audio = await geko.tts.create({ text: req.body.text, voice: req.body.voice });
    res.setHeader("content-type", "audio/wav");
    res.send(Buffer.from(audio));
  } catch (err) {
    const status = err instanceof GekoError ? err.status || 502 : 502;
    res.status(status).json({ error: err instanceof GekoError ? err.detail : "synthesis failed" });
  }
});

app.listen(3000);
```

## Serverless notes

<Note>
  **Cold starts:** the GPU backend scales to zero, so the first request after idle can take tens of seconds. Raise your function's max duration (e.g. Next.js `maxDuration`) and keep the SDK's default 120 s timeout.
</Note>

* **Reuse the client:** construct `new Geko(...)` once at module scope, not per request.
* **Long text? stream it.** For paragraphs or assistant replies, `geko.tts.stream()` starts audio after the first sentence instead of the full render — proxy the chunks straight through. See [Streaming audio](/guides/streaming).
