vilow.dev · Integrations · Bolt.new

Add Vilow to a Bolt.new app

Bolt.new (by StackBlitz) generates full-stack apps in a WebContainer browser sandbox — usually Vite + Express, Next.js or Hono. Because Bolt has a real Node.js runtime, you can keep the Vilow API key in .env and call it from a server-side route. No external proxy needed.

  1. Get a Vilow API key

    Sign in at vilow.dev/dashboardAPI keys → Create. Copy the ck_live_… string.

  2. Add the key to .env in your Bolt project

    Open the file tree, edit .env (Bolt creates it automatically; if not, ask Bolt: "add a .env file with VILOW_API_KEY").

    VILOW_API_KEY=ck_live_...
    VILOW_API_BASE=https://api.vilow.dev/v1
    Don't use VITE_VILOW_API_KEY or any VITE_/NEXT_PUBLIC_ prefix — those bake the value into the client bundle. Plain env vars stay server-only.
  3. Add a server route handler

    For a Bolt-generated Next.js project, create app/api/vilow-chat/route.ts:

    import { NextResponse } from "next/server";
    
    const KEY = process.env.VILOW_API_KEY!;
    const API = process.env.VILOW_API_BASE ?? "https://api.vilow.dev/v1";
    
    export async function POST(req: Request) {
      const { user_id, character_id, message } = await req.json();
    
      let cid = character_id;
      if (!cid) {
        await fetch(`${API}/users`, {
          method: "POST",
          headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
          body: JSON.stringify({ external_id: user_id, display_name: "Bolt visitor" }),
        });
        const r = await fetch(`${API}/users/${user_id}/characters`, {
          method: "POST",
          headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
          body: JSON.stringify({ name: "Aria", gender: "female", default_language: "auto" }),
        });
        cid = (await r.json()).id;
      }
    
      const chat = await fetch(`${API}/chat/${user_id}/${cid}/send`, {
        method: "POST",
        headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
        body: JSON.stringify({ message }),
      });
      return NextResponse.json({ ...(await chat.json()), character_id: cid });
    }

    For Vite + Express: same logic, just an Express route — Bolt's AI will rewrite it for you if you ask.

  4. Call the route from React

    async function send(text) {
      const uid = localStorage.getItem("vilow_uid") ??
        (() => { const u = "u_" + crypto.randomUUID();
                  localStorage.setItem("vilow_uid", u); return u; })();
      const cid = localStorage.getItem("vilow_cid");
    
      const r = await fetch("/api/vilow-chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ user_id: uid, character_id: cid && Number(cid), message: text }),
      });
      const data = await r.json();
      if (data.character_id) localStorage.setItem("vilow_cid", String(data.character_id));
      return data.reply;
    }
  5. Test in Bolt's WebContainer

    Bolt's preview URL is something like {hash}--{slug}.bolt.new. Vilow's API allows that origin out of the box — your route handler is server-side anyway, so the browser never touches Vilow directly.

  6. Deploy

    Bolt offers one-click deploy to Netlify, Vercel, or GitHub. Whichever you pick, copy VILOW_API_KEY into the platform's environment variables before the build.

Common gotchas