shovelbase-js — JavaScript & TypeScript
shovelbase-js gives you one client per project for database, auth, storage, and functions. Install it from shovelbase.com/js.
setup
import { createClient } from 'shovelbase-js'; const shovelbase = createClient( 'https://<project-ref>.shovelbase.com', // Project Settings → API SHOVELBASE_ANON_KEY, // anon key in browsers); // On trusted servers you may use the service key instead — it bypasses RLS:// const admin = createClient(url, SHOVELBASE_SERVICE_ROLE_KEY);Database
// Full PostgREST query surfaceconst { data: clubs } = await shovelbase .from('clubs') .select('id, name, distance') .eq('in_bag', true) .order('distance', { ascending: false }) .limit(20); await shovelbase.from('clubs').insert({ name: '7 iron', distance: 165 });await shovelbase.from('clubs').update({ distance: 170 }).eq('name', '7 iron');await shovelbase.from('clubs').delete().eq('name', '7 iron'); // Call a Postgres functionconst { data } = await shovelbase.rpc('handicap_for', { player_id: 42 });See Table Editor, Migrations, and Permissions for the portal, schema, and RLS side of this.
Auth
// Sign up (no SMTP configured → users are auto-confirmed, session returned)const { data, error } = await shovelbase.auth.signUp({ email: 'me@example.com', password: 'secret123',}); // Sign in / outawait shovelbase.auth.signInWithPassword({ email, password });await shovelbase.auth.signOut(); // Session & userconst { data: { session } } = await shovelbase.auth.getSession();const { data: { user } } = await shovelbase.auth.getUser(); // React to changesshovelbase.auth.onAuthStateChange((event, session) => { /* … */ }); // Admin API (service key client only)await admin.auth.admin.listUsers();await admin.auth.admin.deleteUser(user.id);Once signed in, the client automatically sends the user's JWT, so auth.uid() works in RLS policies and column defaults. Password resets, email templates, and providers are all covered in Authentication.
Storage
// Buckets are created in a migration (insert into storage.buckets) or by a// service-key client:await admin.storage.createBucket('avatars', { public: false }); // Upload / download / list (RLS policies on storage.objects gate access)await shovelbase.storage.from('avatars').upload(`${user.id}.png`, file);const { data: blob } = await shovelbase.storage.from('avatars').download(`${user.id}.png`);const { data: files } = await shovelbase.storage.from('avatars').list(); // URLsconst { data } = shovelbase.storage.from('avatars').getPublicUrl(`${user.id}.png`);const { data: signed } = await shovelbase.storage .from('avatars') .createSignedUrl(`${user.id}.png`, 3600);See Storage for buckets, sharing files, and access control.
Functions
const { data, error } = await shovelbase.functions.invoke('chat', { body: { messages },});Feature flags
// Toggled on the portal (Feature Flags); cached for 60 sif (await shovelbase.flags.isEnabled('new-checkout')) { renderNewCheckout();}See Feature Flags for the full API.
Environment variable conventions
.env
SHOVELBASE_URL=https://<project-ref>.shovelbase.comSHOVELBASE_ANON_KEY=eyJ… # safe in browsersSHOVELBASE_SERVICE_ROLE_KEY=eyJ… # servers only — never ship to a clientIn Vite use the VITE_ prefix (import.meta.env.VITE_SHOVELBASE_ANON_KEY); in Next.js, NEXT_PUBLIC_ for browser-side values. Realtime subscriptions (.channel()) are not supported yet; database, auth, storage, and functions all work.