API Cookbook
Production-ready code examples for common Fluxbase use cases.
Table of Contents
Section titled “Table of Contents”- Getting Started
- Authentication
- Database Operations
- Query Operators
- Realtime Subscriptions
- Storage
- Row-Level Security
- Edge Functions
Getting Started
Section titled “Getting Started”Installation
Section titled “Installation”npm install @fluxbase/sdkInitialize Client
Section titled “Initialize Client”import { createClient } from "@fluxbase/sdk";
const client = createClient("http://localhost:8080", "your-anon-key");Authentication
Section titled “Authentication”Sign Up
Section titled “Sign Up”const { user, session } = await client.auth.signUp({ email: "user@example.com", password: "SecurePass123", options: { data: { name: "John Doe" }, },});Sign In
Section titled “Sign In”const { user, session } = await client.auth.signIn({ email: "user@example.com", password: "SecurePass123",});Sign Out
Section titled “Sign Out”await client.auth.signOut();Get Current User
Section titled “Get Current User”const user = await client.auth.getCurrentUser();if (user) { console.log("Logged in as:", user.email);}Password Reset
Section titled “Password Reset”// Request resetawait client.auth.resetPassword({ email: "user@example.com" });
// User receives email with token, then:await client.auth.confirmPasswordReset({ token: "reset-token", password: "NewPassword123",});Database Operations
Section titled “Database Operations”Select All Rows
Section titled “Select All Rows”const { data, error } = await client.from("posts").select("*");Select Specific Columns
Section titled “Select Specific Columns”const { data } = await client.from("posts").select("id, title, author_id");Select with Joins
Section titled “Select with Joins”const { data } = await client .from("posts") .select("id, title, author(name, email)");Insert Single Row
Section titled “Insert Single Row”const { data } = await client.from("posts").insert({ title: "My Post", content: "Post content", published: true,});Insert Multiple Rows
Section titled “Insert Multiple Rows”const { data } = await client.from("posts").insert([ { title: "Post 1", content: "Content 1" }, { title: "Post 2", content: "Content 2" },]);Update Rows
Section titled “Update Rows”const { data } = await client .from("posts") .update({ published: true }) .eq("author_id", userId);Delete Rows
Section titled “Delete Rows”const { data } = await client.from("posts").delete().eq("id", postId);Upsert (Insert or Update)
Section titled “Upsert (Insert or Update)”const { data } = await client.from("posts").upsert({ id: "existing-id", title: "Updated Title",});Query Operators
Section titled “Query Operators”Equality
Section titled “Equality”// Equalawait client.from("posts").select("*").eq("status", "published");
// Not equalawait client.from("posts").select("*").neq("status", "draft");Comparison
Section titled “Comparison”// Greater thanawait client.from("posts").select("*").gt("views", 1000);
// Greater than or equalawait client.from("posts").select("*").gte("views", 100);
// Less thanawait client.from("posts").select("*").lt("views", 50);
// Less than or equalawait client.from("posts").select("*").lte("views", 10);Pattern Matching
Section titled “Pattern Matching”// Like (case-sensitive)await client.from("posts").select("*").like("title", "%tutorial%");
// ILike (case-insensitive)await client.from("posts").select("*").ilike("title", "%TUTORIAL%");IN Operator
Section titled “IN Operator”await client.from("posts").select("*").in("status", ["published", "featured"]);IS NULL / IS NOT NULL
Section titled “IS NULL / IS NOT NULL”// Nullawait client.from("posts").select("*").is("deleted_at", null);
// Not nullawait client.from("posts").select("*").not("deleted_at", "is", null);Ordering
Section titled “Ordering”// Ascendingawait client.from("posts").select("*").order("created_at", { ascending: true });
// Descendingawait client.from("posts").select("*").order("views", { ascending: false });
// Multiple columnsawait client .from("posts") .select("*") .order("featured", { ascending: false }) .order("created_at", { ascending: false });Pagination
Section titled “Pagination”// Limitawait client.from("posts").select("*").limit(10);
// Offsetawait client.from("posts").select("*").limit(10).offset(20);
// Rangeawait client.from("posts").select("*").range(0, 9); // First 10 rowsCombining Filters
Section titled “Combining Filters”const { data } = await client .from("posts") .select("*") .eq("published", true) .gte("views", 100) .order("created_at", { ascending: false }) .limit(20);Realtime Subscriptions
Section titled “Realtime Subscriptions”Subscribe to Table Changes
Section titled “Subscribe to Table Changes”const channel = client.realtime .channel("table:public.posts") .on("INSERT", (payload) => { console.log("New post:", payload.new_record); }) .on("UPDATE", (payload) => { console.log("Updated post:", payload.new_record); }) .on("DELETE", (payload) => { console.log("Deleted post:", payload.old_record); }) .subscribe();
// Cleanupchannel.unsubscribe();Subscribe to All Events
Section titled “Subscribe to All Events”const channel = client.realtime .channel("table:public.posts") .on("*", (payload) => { console.log("Event:", payload.type, payload); }) .subscribe();React Hook
Section titled “React Hook”import { useEffect, useState } from "react";
function usePosts() { const [posts, setPosts] = useState([]);
useEffect(() => { // Initial load client .from("posts") .select("*") .then(({ data }) => setPosts(data));
// Subscribe to changes const channel = client.realtime .channel("table:public.posts") .on("INSERT", ({ new_record }) => { setPosts((prev) => [...prev, new_record]); }) .on("UPDATE", ({ new_record }) => { setPosts((prev) => prev.map((p) => (p.id === new_record.id ? new_record : p)) ); }) .on("DELETE", ({ old_record }) => { setPosts((prev) => prev.filter((p) => p.id !== old_record.id)); }) .subscribe();
return () => channel.unsubscribe(); }, []);
return posts;}Storage
Section titled “Storage”Upload File
Section titled “Upload File”const file = document.getElementById("fileInput").files[0];
const { data, error } = await client.storage .from("avatars") .upload("user-123.png", file);Download File
Section titled “Download File”const { data } = await client.storage.from("avatars").download("user-123.png");
// Create download linkconst url = URL.createObjectURL(data);const a = document.createElement("a");a.href = url;a.download = "avatar.png";a.click();List Files
Section titled “List Files”const { data: files } = await client.storage.from("avatars").list();
files.forEach((file) => { console.log(file.name, file.size);});Delete File
Section titled “Delete File”await client.storage.from("avatars").remove(["user-123.png"]);Get Public URL
Section titled “Get Public URL”const url = client.storage.from("public-bucket").getPublicUrl("logo.svg");Create Signed URL (Private Files)
Section titled “Create Signed URL (Private Files)”const { data } = await client.storage .from("private-docs") .createSignedUrl("document.pdf", 3600); // 1 hour expiry
console.log("Temporary URL:", data.signedUrl);Row-Level Security
Section titled “Row-Level Security”Enable RLS on Table
Section titled “Enable RLS on Table”ALTER TABLE posts ENABLE ROW LEVEL SECURITY;User Can Only See Own Posts
Section titled “User Can Only See Own Posts”CREATE POLICY "Users see own posts"ON posts FOR SELECTUSING (current_setting('app.user_id', true)::uuid = user_id);User Can Only Insert Own Posts
Section titled “User Can Only Insert Own Posts”CREATE POLICY "Users insert own posts"ON posts FOR INSERTWITH CHECK (current_setting('app.user_id', true)::uuid = user_id);Public Read, Auth Write
Section titled “Public Read, Auth Write”-- Anyone can readCREATE POLICY "Public read"ON posts FOR SELECTUSING (true);
-- Only authenticated can writeCREATE POLICY "Auth write"ON posts FOR INSERTWITH CHECK (current_setting('app.role', true) = 'authenticated');Admin Access
Section titled “Admin Access”CREATE POLICY "Admin full access"ON posts FOR ALLUSING (current_setting('app.role', true) = 'admin');Edge Functions
Section titled “Edge Functions”Create Function
Section titled “Create Function”await client.functions.create({ name: "send-email", code: ` async function handler(req) { const { to, subject, body } = JSON.parse(req.body || '{}')
// Send email logic here
return { status: 200, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ success: true }) } } `, enabled: true,});Invoke Function
Section titled “Invoke Function”const result = await client.functions.invoke("send-email", { to: "user@example.com", subject: "Hello", body: "Welcome to Fluxbase!",});Function with Database Access
Section titled “Function with Database Access”await client.functions.create({ name: "get-stats", code: ` async function handler(req) { // Access database via client const dbUrl = Deno.env.get('DATABASE_URL')
// Your logic here
return { status: 200, body: JSON.stringify({ stats: 'data' }) } } `,});Common Patterns
Section titled “Common Patterns”Todo App
Section titled “Todo App”// Create todos table first/*CREATE TABLE todos ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id), title TEXT NOT NULL, completed BOOLEAN DEFAULT false, created_at TIMESTAMPTZ DEFAULT NOW());
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users see own todos"ON todos FOR ALLUSING (current_setting('app.user_id', true)::uuid = user_id);*/
// Get todosconst { data: todos } = await client .from("todos") .select("*") .order("created_at", { ascending: false });
// Add todoawait client.from("todos").insert({ title: "Buy groceries", user_id: currentUser.id,});
// Toggle completedawait client.from("todos").update({ completed: true }).eq("id", todoId);
// Delete todoawait client.from("todos").delete().eq("id", todoId);Blog Posts with Comments
Section titled “Blog Posts with Comments”// Create tables/*CREATE TABLE posts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), author_id UUID REFERENCES auth.users(id), title TEXT NOT NULL, content TEXT, published BOOLEAN DEFAULT false, created_at TIMESTAMPTZ DEFAULT NOW());
CREATE TABLE comments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), post_id UUID REFERENCES posts(id) ON DELETE CASCADE, author_id UUID REFERENCES auth.users(id), content TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW());*/
// Get posts with commentsconst { data: posts } = await client .from("posts") .select( ` id, title, content, author(name, email), comments(id, content, author(name)) ` ) .eq("published", true) .order("created_at", { ascending: false });User Profiles
Section titled “User Profiles”// Create profiles table/*CREATE TABLE profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id), username TEXT UNIQUE, avatar_url TEXT, bio TEXT, created_at TIMESTAMPTZ DEFAULT NOW());
-- Auto-create profile on user signupCREATE OR REPLACE FUNCTION handle_new_user()RETURNS TRIGGER AS $$BEGIN INSERT INTO public.profiles (id, username) VALUES (NEW.id, NEW.email); RETURN NEW;END;$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION handle_new_user();*/
// Get user profileconst { data: profile } = await client .from("profiles") .select("*") .eq("id", userId) .single();
// Update profileawait client .from("profiles") .update({ bio: "My new bio", avatar_url: "https://..." }) .eq("id", userId);Error Handling
Section titled “Error Handling”try { const { data, error } = await client.from("posts").select("*");
if (error) { console.error("Query error:", error.message); return; }
console.log("Posts:", data);} catch (err) { console.error("Network error:", err);}