Product Docs Pricing Changelog
Start free Sign in
Docs / Frameworks / Vite + React

Vite + React (browser-only SPA)

A pure SPA can only call flarelink.auth.*. Database and storage need the service key — put those behind your own API (a small Worker, a Vercel function, etc.) and have the SPA call that. Never ship the service key in a Vite bundle (anything in import.meta.env that isn't VITE_-prefixed stays server-side; even so, don't put the key in the SPA).

// src/flarelink.ts import { createFlarelink } from "@flarelink/client" export const flarelink = createFlarelink({ url: import.meta.env.VITE_FLARELINK_AUTH_URL, })
// src/App.tsx import { useEffect, useState } from "react" import { flarelink } from "./flarelink" import type { User } from "@flarelink/client" export default function App() { const [me, setMe] = useState<User | null>(null) useEffect(() => { flarelink.auth.getMe().then(setMe) }, []) return <div>{me ? `Hi, ${me.name}` : "Signed out"}</div> }

Protect a route

In a SPA the guard is a client-side gate: call getMe(), show a loader while it resolves, then render or redirect. This is a UX guard, not a security boundary — the real authorization happens server-side in the API the SPA calls.

// src/RequireAuth.tsx import { useEffect, useState } from "react" import { Navigate } from "react-router-dom" import { flarelink } from "./flarelink" import type { User } from "@flarelink/client" export function RequireAuth({ children }: { children: React.ReactNode }) { const [state, setState] = useState<"loading" | User | null>("loading") useEffect(() => { flarelink.auth.getMe().then(setState).catch(() => setState(null)) }, []) if (state === "loading") return <p>Loading…</p> if (!state) return <Navigate to="/login" replace /> return <>{children}</> }
A client-side guard only hides UI. Your data API must independently call getMe() (with the cookie forwarded) and scope every query to that user — see Hono / Workers for a matching API.
# .env VITE_FLARELINK_AUTH_URL=https://myapp-auth.your-subdomain.workers.dev
Something unclear or missing? hello@flarelink.dev llms-full.txt ↗