vilow.dev · Integrations · Lovable
Add Vilow to a Lovable app
Lovable generates React/Next.js apps from prompts. To give your app a stateful AI companion (memory + emotions + relationships), call Vilow's REST API. We'll use Lovable's recommended Supabase backend to keep the API key server-side — exposing it in client code would let any visitor spend your credits.
-
Get a Vilow API key
Open vilow.dev/dashboard → sign in with email (magic link) → tab API keys → click Create key. You'll get something that starts with
ck_live_. Copy it once — you won't see it again. -
Connect Supabase to your Lovable project
In Lovable: Settings → Integrations → Supabase → Connect. Lovable will create (or attach) a Supabase project and start using it for auth, database, and Edge Functions. This is where our API key will live.
Already using a different backend? Skip Supabase and adapt step 3 to your platform's secret-store + serverless-function equivalent — the principle is identical.
-
Store the Vilow API key as a Supabase secret
In Supabase Dashboard: Edge Functions → Secrets → Add new. Name it
VILOW_API_KEY, paste theck_live_…value.Why not just put it in Lovable's environment? Lovable env vars are baked into the client bundle and visible in DevTools. Supabase Edge Function secrets are server-only — that's where the key belongs. -
Create an Edge Function as a thin proxy
Ask Lovable: "Add a Supabase Edge Function called
vilow-chatthat proxies POST requests tohttps://api.vilow.dev/v1/chat/{user}/{character}/sendusing theVILOW_API_KEYsecret."If you'd rather paste it yourself, Lovable will accept this:
// supabase/functions/vilow-chat/index.ts import { serve } from "https://deno.land/std/http/server.ts"; const VILOW_KEY = Deno.env.get("VILOW_API_KEY")!; const VILOW_API = "https://api.vilow.dev/v1"; serve(async (req) => { if (req.method !== "POST") return new Response("POST only", { status: 405 }); const { user_id, character_id, message, persona } = await req.json(); // Lazy-create the character on first turn (no character_id yet). let cid = character_id; if (!cid) { await fetch(`${VILOW_API}/users`, { method: "POST", headers: { "X-API-Key": VILOW_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ external_id: user_id, display_name: "Lovable visitor" }), }); const r = await fetch(`${VILOW_API}/users/${user_id}/characters`, { method: "POST", headers: { "X-API-Key": VILOW_KEY, "Content-Type": "application/json" }, body: JSON.stringify(persona ?? { name: "Aria", gender: "female", default_language: "auto" }), }); cid = (await r.json()).id; } const chat = await fetch(`${VILOW_API}/chat/${user_id}/${cid}/send`, { method: "POST", headers: { "X-API-Key": VILOW_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ message }), }); const data = await chat.json(); return new Response(JSON.stringify({ ...data, character_id: cid }), { headers: { "Content-Type": "application/json" }, }); });
-
Call the Edge Function from your Lovable React
Drop a chat input + send handler into your component:
// In any Lovable-generated React component const [characterId, setCharacterId] = useState( () => localStorage.getItem("vilow_cid"), ); const userId = useMemo(() => { let u = localStorage.getItem("vilow_uid"); if (!u) { u = "u_" + crypto.randomUUID(); localStorage.setItem("vilow_uid", u); } return u; }, []); async function send(text) { const r = await supabase.functions.invoke("vilow-chat", { body: { user_id: userId, character_id: characterId, message: text }, }); if (r.data?.character_id && r.data.character_id !== characterId) { setCharacterId(r.data.character_id); localStorage.setItem("vilow_cid", r.data.character_id); } return r.data?.reply; }
-
Test from Lovable's preview
Lovable's hot-reload preview runs on a
*.lovable.appURL. Our API already allows that origin via CORS, so the Edge-Function call works from the live preview without extra setup. Send a message — you should see the character reply with growing memory across turns.Sanity-check via curl from your terminal too:
curl -X POST https://api.vilow.dev/v1/chat/u_test/CID/send \ -H "X-API-Key: ck_live_..." \ -H "Content-Type: application/json" \ -d '{"message":"Hi, what was the last thing we talked about?"}'
-
Ship it
Lovable deploys to
{slug}.lovable.appautomatically. Custom domains: Settings → Domains → Add. Edge Function secrets and CORS continue to work on custom domains.
Common gotchas
- "VILOW_API_KEY undefined" in the function — secrets need to be redeployed:
supabase functions deploy vilow-chatafter changing them. - 402 Payment Required — your tenant ran out of free messages. Upgrade plan in dashboard or wait for next billing period.
- "Character not found" on second message — you forgot to persist
character_idafter the first reply. Use localStorage (per-visitor) so it survives reloads. - Replies are too short or too generic — pass a richer
persona+backstoryon character creation. See docs for the personality engine fields.
What you got
Your Lovable app now has an AI companion that remembers conversations across sessions, develops emotions and a relationship with each visitor, and sounds increasingly like a person, not a chatbot. To go further: voice replies, intimate-mode (consent-gated), Snapshot Import (clone someone from a description) — all opt-in via the same API. See the main docs.