shovelbasedocs

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 surface
const { 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 function
const { 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 / out
await shovelbase.auth.signInWithPassword({ email, password });
await shovelbase.auth.signOut();
// Session & user
const { data: { session } } = await shovelbase.auth.getSession();
const { data: { user } } = await shovelbase.auth.getUser();
// React to changes
shovelbase.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();
// URLs
const { 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 s
if (await shovelbase.flags.isEnabled('new-checkout')) {
renderNewCheckout();
}

See Feature Flags for the full API.

Environment variable conventions

.env
SHOVELBASE_URL=https://<project-ref>.shovelbase.com
SHOVELBASE_ANON_KEY=eyJ # safe in browsers
SHOVELBASE_SERVICE_ROLE_KEY=eyJ # servers only — never ship to a client

In 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.