build strategy · FLock.io

Real FLock.io, one key, one build.

Every mega-prompt in this archive collapses into the same shape: a single TanStack server function calling api.flock.io with one secret. It's the only pattern that lets a Lovable account ship a working FLock demo in one shot, inside the 5-credit budget.

Why FLock.io and not a single provider?

FLock.io fronts a decentralised model marketplace with one OpenAI-compatible endpoint and one API key — DeepSeek V4, Gemini 3.1 Pro, Kimi K2.6, Qwen3, MiniMax and Zai for chat; Nano Banana 2 and Gemini 3 Flash for images; Kimi K2.5 for video; every tools- capable model for agents. Swap models by changing one string, never touch infra.

Why TanStack server functions?

Lovable's TanStack Start template makes secrets trivial. createServerFn runs on the server, reads process.env.FLOCK_API_KEY, hits FLock via the x-litellm-api-key header, and returns typed JSON. The key never reaches the browser, no edge functions or extra infra needed.

The pattern in code.

src/lib/flock.functions.ts — chat
// src/lib/flock.functions.ts — TanStack server function calling FLock chat completions
// Built during the FLock.io Creative Hackathon — StreetKode Fam · Indian Krump Festival 14
import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";

export const ask = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ topic: z.string().min(1).max(2000) }).parse(d))
  .handler(async ({ data }) => {
    const r = await fetch("https://api.flock.io/v1/chat/completions", {
      method: "POST",
      headers: {
        "x-litellm-api-key": process.env.FLOCK_API_KEY!,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "qwen3-30b-a3b-instruct-2507",
        messages: [{ role: "user", content: data.topic }],
      }),
    });
    if (!r.ok) throw new Error(`FLock failed: ${r.status}`);
    const j = await r.json();
    return { reply: j.choices[0].message.content as string };
  });
src/lib/flock.functions.ts — image
// src/lib/flock.functions.ts — same key, generate an image
export const render = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ brief: z.string().min(1).max(800) }).parse(d))
  .handler(async ({ data }) => {
    const r = await fetch("https://api.flock.io/v1/chat/completions", {
      method: "POST",
      headers: {
        "x-litellm-api-key": process.env.FLOCK_API_KEY!,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "nano-banana-2",
        modalities: ["image", "text"],
        messages: [{ role: "user", content: data.brief }],
      }),
    });
    if (!r.ok) throw new Error(`FLock image failed: ${r.status}`);
    const j = await r.json();
    const url = j.choices[0].message.images?.[0]?.image_url?.url;
    return { url: url as string };
  });
.env + Lovable build
# .env (Lovable -> Project Settings -> Secrets)
FLOCK_API_KEY=sk-...           # https://platform.flock.io

# How Lovable wires this up in one prompt:
# 1. Paste a mega-prompt from this archive.
# 2. Lovable
#    - writes a server function that proxies FLock (chat / image / video / agents)
#    - wires the client surface (textarea, prompt-to-canvas, task box, etc.)
#    - keeps your key on the server via process.env.FLOCK_API_KEY
# 3. Run it. Your demo is calling real FLock.io frontier models.

Shipping a 5-credit demo