Works with · Lovable

Lovable + Cerver: see what your users' AI actually costs.

Lovable turns prompts into full React + Supabase apps — 100k+ new projects a day. What it doesn't give you: any idea what your users' AI usage costs, who your expensive users are, or a key you can safely ship. That's a backend problem — and it's one prompt away from solved.

The gap in every vibe-coded AI app

Lovable will happily wire an AI feature — usually by putting a provider API key somewhere it shouldn't be and calling it a day. Then reality arrives on schedule: the key leaks (a June study caught 282 apps exposing theirs), one enthusiastic user quietly becomes most of your bill, and you can't answer the only business question that matters: what does each user's AI usage cost me?

Cerver is the piece Lovable doesn't build: a session gateway between your app and every model. Your app talks to two endpoints with a publishable key (scoped, $5/day budget, 60 req/min — designed to ship in clients). Every user gets a session; every session carries app_user_id; every dollar lands in a dashboard you can query.

Usage per userevery user's sessions, transcripts, and exact cost — by name
Caps that holdbudget + rate limit enforced at the gateway, not in your code
Any modelswap providers with one string — benchmarks here

The integration is a prompt

You built the app by prompting — integrate the backend the same way. Paste this into Lovable:

paste into Lovable
Add an AI assistant to my app, powered by cerver.ai (an AI-backend gateway).

Requirements:
1. All AI calls go through Cerver's gateway — two endpoints only:
   - POST https://gateway.cerver.ai/v2/sessions
     body: { "compute": {"provider": "online"}, "metadata": {"app_user_id": "<current user id>"} }
     → returns { "session_id": ... }. Create ONE session per user, cache the id.
   - POST https://gateway.cerver.ai/v2/sessions/<id>/run-llm
     body: { "input": "<user message>", "model": "claude-haiku-4-5-20251001", "harness": "claude" }
     → Server-Sent Events stream; "event: text_delta" lines carry data JSON with a "content" chunk.
2. Auth header on both calls: Authorization: Bearer <CERVER_PUBLISHABLE_KEY>
   (React client (publishable key) or Supabase Edge Function (secret key)). NEVER put an OpenAI/Anthropic key anywhere in this app.
3. Always send metadata.app_user_id on session create — per-user cost attribution depends on it.
4. Stream the reply into the UI as chunks arrive; show a small "thinking" state until the first chunk.
5. Keep the model id in ONE constant so it can be swapped later.
6. Add a friendly retry state for failed/refused runs.

The publishable key is scoped server-side to these two endpoints and carries a $5/day budget
and 60 req/min rate limit — it is designed to ship in the client.

Before pasting, mint the key (once, from your terminal — your secret key never enters Lovable):

curl -X POST https://gateway.cerver.ai/v2/auth/keys \
  -H "Authorization: Bearer $CERVER_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "label": "lovable-app", "project_slug": "my-app", "kind": "publishable" }'
# → { "key": "pk_XXXX…" } — that's the one that goes in the app

What the generated code looks like

If you'd rather read it than prompt it — the whole client is two functions (React client (publishable key) or Supabase Edge Function (secret key)):

const GW = "https://gateway.cerver.ai";
const PK = "pk_XXXX…"; // publishable key — scoped + capped, safe for clients

// one session per user — the transcript is their AI history
export async function cerverSession(userId) {
  const cached = localStorage.getItem("cerver.session");
  if (cached) return cached;
  const r = await fetch(`${GW}/v2/sessions`, {
    method: "POST",
    headers: { Authorization: `Bearer ${PK}`, "Content-Type": "application/json" },
    body: JSON.stringify({
      compute: { provider: "online" },
      metadata: { app_user_id: userId }   // ← this is what makes usage queryable per user
    })
  });
  const j = await r.json();
  const sid = j.session_id || j.sessionId;
  localStorage.setItem("cerver.session", sid);
  return sid;
}

// streamed reply (SSE)
export async function ask(sessionId, input, onDelta) {
  const r = await fetch(`${GW}/v2/sessions/${sessionId}/run-llm`, {
    method: "POST",
    headers: { Authorization: `Bearer ${PK}`, "Content-Type": "application/json" },
    body: JSON.stringify({ input, model: "claude-haiku-4-5-20251001", harness: "claude" })
  });
  const reader = r.body.getReader(), dec = new TextDecoder();
  let buf = "", event = "";
  for (;;) {
    const { done, value } = await reader.read();
    if (done) break;
    buf += dec.decode(value, { stream: true });
    const lines = buf.split("\n"); buf = lines.pop();
    for (const line of lines) {
      if (line.startsWith("event: ")) event = line.slice(7).trim();
      else if (line.startsWith("data: ") && event === "text_delta") {
        try { onDelta(JSON.parse(line.slice(6)).content || ""); } catch {}
      }
    }
  }
}

Then: query your users' AI usage

This is the part that changes how you run the product. Open your Cerver dashboard → Sessions, and every user is there: their transcript history, their session count, their exact spend. The user costing you $2/day isn't a leak — it's your Pro tier waiting to be priced. The feature nobody uses isn't a mystery — the transcripts say what people actually ask. And when a better model ships, check the benchmark, change one string in your Lovable project, done.

Two endpoints. One prompt. Every answer about your AI costs.

Open a project, mint a publishable key, paste the prompt into Lovable. No card, $5 free tier.