Start

Connect a frontend

Host and edit the UI on Robodev, or point Lovable, Bolt, v0, and other tools at the same project host.

A Robodev project host can serve the UI and the APIs together. Create from a starter in the dashboard or with robodev create, then edit on the Code page. Hosted React builds set VITE_API_URL to empty and use window.location.origin. You can still point Lovable, Bolt, v0, or local Vite at the same host.

Hosted on Robodev

  • Create and deploy a starter from the dashboard. The Code page edits the stored file tree; Save deploys the full tree.
  • index.html plus src/main.tsx (or .ts / .jsx / .js) is a React app. Starbase bundles it. index.html alone is a static site. No index.html is API-only.
  • Space, Auth chat, and Marketplace: robodev create / deploy with .robodev frontend set runs the local Vite build and uploads that static site. Dashboard create stays API-only.
  • Blessed browser packages: react, react-dom, and @robodev-ai/client. User package.json scripts and vite.config are not run.
  • Swagger stays at /_robodev/docs so a React app can own /docs.

Lovable, Bolt, and similar web-container tools can deploy a Robodev backend from inside the tool with robodev-be. Do not run the full robodev CLI there — it needs browser OAuth and home-dir credentials. Generate a prompt on the project Lovable / Bolt page, paste it into the tool, and let it run robodev-be auth and robodev-be deploy.

Generate a prompt in the dashboard

  • Open the project’s Lovable / Bolt page at /projects/:id/builders.
  • Choose Lovable, Bolt, or Other, then Generate prompt. That creates a one-time deploy key and a paste-ready prompt.
  • Paste the prompt into the tool. It installs robodev-be, writes database.ts and api/**/*.ts at the workspace root, and deploys the backend only.
  • Read the hosted backend URL from .robodev as projectApiUrl (not apiUrl) and set VITE_API_URL to that value.

If the tool has no terminal (for example v0), keep the UI in that tool and run robodev-be on a real machine. The dashboard prompt tells the model to do that.

Robodev vs Supabase

  • Robodev: TypeScript database.ts plus api/*.ts, deployed with robodev-be deploy from a builder or robodev deploy from a real machine. The browser talks with fetch and VITE_API_URL, or with @robodev-ai/client.
  • Not Supabase: no @supabase/supabase-js, no PostgREST .from(), no realtime, no RLS. File storage is Robodev storage via injected ctx.storage in defineApi, not the Supabase Storage API.
  • End-user login is Robodev Auth on the project host (Bearer tokens). See Auth (/docs/auth). It is not the Starbase dashboard login.
  • Discover routes from OpenAPI on the project host. Do not invent endpoints.

Routes default to public (auth: false). Anyone who knows the URL can call those. CORS allows all browser origins. For protected routes, send Authorization: Bearer <accessToken> from Robodev Auth. Do not invent a JWT or cookie session that the backend does not check.

Fetch and env contract

Set VITE_API_URL to the project API URL with no trailing slash. After robodev-be auth, read it from .robodev as projectApiUrl. robodev create and robodev link write this for the starter. If the tool is not Vite, set its public env var to the same URL and read that name instead — the URL contract does not change.

fetch

function projectApiUrl(): string {
const fromEnv = import.meta.env.VITE_API_URL;
if (typeof fromEnv === "string" && fromEnv.trim()) return fromEnv.replace(/\/+$/, "");
if (typeof window !== "undefined") return window.location.origin;
return "";
}
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const apiUrl = projectApiUrl();
const res = await fetch(`${apiUrl}${path}`, {
...init,
headers: { "Content-Type": "application/json", ...init?.headers },
});
if (!res.ok) {
throw new Error((await res.text()) || `${res.status} ${path}`);
}
return res.json() as Promise<T>;
}
const planets = await request<Planet[]>("/api/planets");
await request("/api/planets", {
method: "POST",
body: JSON.stringify({ name: "Mars" }),
});
// Protected route (GET /api/me in the starter):
const token = localStorage.getItem("accessToken");
const me = await request<{ user: { id: string; email: string } }>("/api/me", {
headers: token ? { Authorization: `Bearer ${token}` } : {},
});

Optional @robodev-ai/client

Prefer the small browser client when you need signup, login, and Bearer attachment. It is not React hooks. File uploads go through your own defineApi handlers. How-to: Auth (/docs/auth) and Storage (/docs/storage).

client

import { createClient } from "@robodev-ai/client";
const api = createClient({ url: import.meta.env.VITE_API_URL });
await api.auth.signIn.email({ email, password });
const { user } = await api.auth.getUser();
const me = await api.fetch("/api/me").then((r) => r.json());

Project hosts

  • Production API: https://{projectId}.robodev.povio.dev
  • OpenAPI: {VITE_API_URL}/openapi.json
  • Swagger UI: {project host}/_robodev/docs — not https://robodev.povio.dev/docs
  • Copy the API URL from the project page in Starbase, from robodev projects, or from robodev deploy output.

Backend with robodev-be

Tools that can run npm/npx write database.ts and api/*.ts in the workspace and deploy with robodev-be. Do not run the full robodev CLI (browser OAuth) inside those tools. Do not invent endpoints; after deploy, read OpenAPI. If a tool cannot run a terminal, tell the human to run the same robodev-be commands on a real machine.

Fallback prompt for tools with no terminal

Prefer Generate prompt on the project Lovable / Bolt page. For a tool that cannot run npm/npx, paste the frontend-only block below together with the project API URL.

prompt

You are building ONLY the frontend. Do not use Supabase.
The backend is Robodev, not Supabase, not PostgREST, not Firebase.
Rules:
- Do not install or import @supabase/supabase-js or any Supabase client.
- Do not use Supabase createClient, .from(), .auth, realtime, or storage APIs.
- Optional Robodev client: @robodev-ai/client (createClient + auth + fetch). Not required — platform fetch is fine.
- Call the project API with fetch and one env var: VITE_API_URL (no trailing slash).
- If this tool is not Vite, set its public env to the same URL and read that variable instead.
- Production API: https://{projectId}.robodev.povio.dev
- OpenAPI JSON: {VITE_API_URL}/openapi.json
- Swagger UI: {project host}/_robodev/docs on the PROJECT host (not the marketing site /docs).
- CORS allows all browser origins.
- Routes are public unless OpenAPI marks them with bearerAuth (or the handler uses auth: "required"). Public routes stay public — do not invent a login wall for them.
- End-user auth is Robodev Auth on the project host: POST /api/user/auth/register, POST /api/user/auth/login, POST /api/user/auth/refresh, GET /api/user/me. Store accessToken and refreshToken and send Authorization: Bearer <accessToken>. Not cookies. Not the Starbase dashboard JWT.
- File storage is Robodev storage via your defineApi handlers (multipart + ctx.storage.upload). Public files are served at GET /storage/objects/{key}. Do not use the Supabase Storage API.
- There is no realtime or row-level security. Wrap storage in your own handlers for access control.
- JSON in, JSON out. Send Content-Type: application/json on writes.
- Discover routes from OpenAPI. Use only routes that exist. Do not invent backend endpoints.
- If a route you need is missing, tell the human to add database.ts / api/*.ts and run `robodev deploy` outside this tool, then refresh OpenAPI.
Fetch helper:
const apiUrl = import.meta.env.VITE_API_URL as string | undefined;
async function request<T>(path: string, init?: RequestInit): Promise<T> {
if (!apiUrl) {
throw new Error("Missing VITE_API_URL. Set it to your Robodev project URL.");
}
const res = await fetch(`${apiUrl}${path}`, {
...init,
headers: { "Content-Type": "application/json", ...init?.headers },
});
if (!res.ok) {
throw new Error((await res.text()) || `${res.status} ${path}`);
}
return res.json() as Promise<T>;
}
Example:
const planets = await request<Planet[]>("/api/planets");
await request("/api/planets", { method: "POST", body: JSON.stringify({ name: "Mars" }) });
The human will paste VITE_API_URL. Prefer the dashboard Lovable / Bolt page and robodev-be when the tool has a terminal.

Next

Create a project, open Lovable / Bolt, generate a prompt, and paste it into the tool. Getting started is at /docs.