Product Docs Pricing Changelog
Start free Sign in
Docs / Getting started / Quickstart

Quickstart

A working backend — auth, database, storage — on your own Cloudflare account, in about five minutes.

You'll need a Cloudflare account and a scoped API token. The token is the only secret Flarelink ever sees — your D1, R2, and Worker config all live on your account, not ours.
Coming from Supabase? Flarelink is server-first: the browser can only call flarelink.auth.*; database and storage go through your server with the service key, and there's no row-level security yet. The query builder looks like Supabase's, but the trust model is different — read Architecture: server-first by design so nothing surprises you.

1. Connect your Cloudflare

Sign up at dash.flarelink.dev, then create a scoped Cloudflare API token with these permissions:

Required — all account-scoped:

  • Account → Workers Scripts: Edit
  • Account → D1: Edit
  • Account → Workers KV Storage: Edit
  • Account → Workers R2 Storage: Edit

Optional:

  • User → API Tokens: Edit — lets Flarelink mint a scoped R2 keypair for you with one click. This is a token-minting permission; if you'd rather not grant it, leave it out and paste your own R2 keypair on the Files page instead. Everything else works the same. See What the token can do.

Paste the token on /connect-cf. Flarelink validates it against your account before storing it AES-256-GCM encrypted. Connect succeeds with or without the optional scope.

2. Provision a project

Click New project. The wizard provisions everything in one atomic operation:

  • A D1 database for your users (with the auth schema applied)
  • A KV namespace for sessions
  • An auth Worker uploaded to your account on *.workers.dev
  • A service key for the SDK, shown exactly once

R2 storage is optional — you can attach it later from the project's Storage panel when you need to handle files. If any provisioning step fails, the whole thing rolls back; you won't end up with half a backend.

The service key is shown exactly once in the secret-bundle modal. Copy it somewhere safe before dismissing — Flarelink stores only a SHA-256 hash and can't recover the plaintext. Lost it? Hit Rotate service key on the project's Auth panel.
Before production: attach a custom domain. The default *.workers.dev URL is cross-site to your app, so the session cookie is a third-party cookie — and Safari and iOS block those, which means sign-in silently fails for those users. Attaching auth.yourdomain.com on your app's own domain makes the cookie same-site and fixes it. workers.dev is fine for local testing; switch before you ship. See Cookies & Safari and Custom domain for auth.

3. Install & configure

Add @flarelink/client to your app — works on Node, Bun, Cloudflare Workers, Vercel, anywhere.

npm install @flarelink/client

Add the auth Worker URL and the service key to your env. The naming below matches the rest of these docs — use whatever your framework prefers.

# .env / .env.local / .dev.vars FLARELINK_AUTH_URL=https://myapp-auth.your-subdomain.workers.dev FLARELINK_SERVICE_KEY=flarelink_sk_… # server-only, NEVER in browser bundles

4. Set trusted origins (don't skip)

In your project's Auth panel, add every origin your app runs on — production, staging, http://localhost:3000 for dev. The Worker rejects requests from anywhere else with a 403.

This is the most common misconfiguration. If sign-in returns 403 with MISSING_OR_NULL_ORIGIN, add your origin and try again. Developing locally? See Local development for the localhost-over-HTTPS setup Safari needs.

5. Use it

In the browser, only flarelink.auth.* is callable — no service key.

// app/login.ts — browser import { createFlarelink } from "@flarelink/client" const flarelink = createFlarelink({ url: process.env.FLARELINK_AUTH_URL! }) await flarelink.auth.signIn({ email, password }) const me = await flarelink.auth.getMe() // User | null

On the server, add the service key — you get the full surface: database + storage + auth.

// app/server.ts — server import { createFlarelink } from "@flarelink/client" const flarelink = createFlarelink({ url: process.env.FLARELINK_AUTH_URL!, serviceKey: process.env.FLARELINK_SERVICE_KEY!, }) // Database — every query resolves to { rows, meta } const { rows: posts } = await flarelink .from<Post>("posts") .where({ author_id: userId }) .orderBy("created_at", "desc") .limit(20) // Storage — mint a presigned PUT, browser uploads to R2 directly const { url, signedHeaders } = await flarelink.storage .from("uploads") .createSignedUploadUrl("avatars/me.png", { contentType: "image/png" })

That's the whole loop. Next steps:

Something unclear or missing? hello@flarelink.dev llms-full.txt ↗