name: nano-supabase description: > Skill for working with the nano-supabase codebase: a lightweight TypeScript library that emulates Supabase entirely in-browser/edge using PGlite (Postgres via WASM). Covers architecture, fetch adapter routing, auth/storage/data flows, PostgREST WASM parser, connection pooling, cross-runtime compatibility, build system, and testing conventions. Use when implementing features, fixing bugs, writing tests, or reviewing code in this project.
nano-supabase
Lightweight Supabase emulation running entirely in-browser/edge. Zero network calls. Full auth (JWT + RLS), storage (pluggable backends), PostgREST query parsing (WASM), priority-queue connection pooling over PGlite.
Architecture
@supabase/supabase-js
-> Fetch Adapter (routes by URL path)
/auth/v1/* -> AuthHandler (signup, signin, signout, refresh)
/rest/v1/* -> PostgREST Parser (WASM) -> SQL
/storage/v1/* -> StorageHandler (buckets, objects, signed URLs)
-> Priority Queue (CRITICAL / HIGH / MEDIUM / LOW)
-> Connection Pooler (N-to-1 multiplexing)
-> PGlite (PostgreSQL in WebAssembly)
Project Layout
src/
index.ts # Public exports
client.ts # createLocalSupabaseClient, createFetchAdapter
supabase-client.ts # Supabase-compatible client wrapper
postgrest-parser.ts # PostgREST -> SQL (WASM binding)
pooler.ts # N-to-1 connection pooler
queue.ts # Priority queue (4 levels)
types.ts # QueryPriority, QueryResult, PoolerConfig
auth/ # JWT via Web Crypto, sessions, refresh tokens
handler.ts # signUp, signIn, signOut, refreshToken
crypto.ts # Web Crypto API helpers
jwt.ts # signJWT, verifyJWT, decodeJWT
schema.ts # Auth SQL schema (CREATE IF NOT EXISTS)
types.ts # User, Session, AuthResponse
storage/ # Storage API emulation
handler.ts # Bucket/object CRUD
backend.ts # StorageBackend interface + MemoryStorageBackend
schema.ts # Storage SQL schema
fetch-adapter/ # Intercepts supabase-js fetch calls
index.ts # createLocalFetch: URL routing
auth-routes.ts # /auth/v1/* dispatch
data-routes.ts # /rest/v1/* dispatch
storage-routes.ts # /storage/v1/* dispatch
auth-context.ts # JWT claims extraction for RLS
error-handler.ts # Error -> Response conversion
tests/
compat.ts # Deno/Bun test shim (runtime-agnostic)
*.test.ts # Split by concern: auth, data, storage, fetch-adapter, applications, full-user-flow
Key Technical Details
- TypeScript strict mode, ESNext modules, ES2022 target
- Cross-runtime: Node.js, Deno, Bun, Browser, Cloudflare Workers. Use Web Crypto API only (no Node crypto)
- PGlite is a peer dependency - users provide their own instance
- postgrest-parser bundled as WASM in dist/
- esbuild bundles to dist/index.js (~21KB) + WASM (~377KB)
- SQL schemas use
CREATE IF NOT EXISTSfor idempotent initialization - RLS functions:
auth.uid(),auth.role(),auth.email()backed by PostgreSQL roles (anon,authenticated,service_role)
Common Patterns
Create a client:
const client = createLocalSupabaseClient(db);
// or manually:
const client = createClient(url, key, { global: { fetch: createLocalFetch(db, key) } });
Auth flow:
await supabase.auth.signUp({ email, password });
const { data: { session } } = await supabase.auth.signInWithPassword({ email, password });
// JWT now in session, RLS active
Data with RLS:
// Create table + RLS policy, then query as authenticated user
const { data } = await supabase.from('todos').select('*');
// Only returns rows matching RLS policy
Storage:
await supabase.storage.from('avatars').upload('path/file.png', blob);
const { data } = await supabase.storage.from('avatars').download('path/file.png');
const { data: { signedUrl } } = await supabase.storage.from('avatars').createSignedUrl('path/file.png', 3600);
Testing
- Behavior over implementation: Test real user workflows, not internals
- No helper files: Inline all setup for full context at each test
- No excessive mocking: Use real PGlite instances
- Each test creates its own PGlite instance + client (isolated)
- Full workflows: signup -> insert -> query -> verify RLS -> cleanup
- Runtime-agnostic via
compat.tsshim
Run tests:
deno test --allow-read --allow-env tests/
bun test tests/
Build
npm run build # esbuild -> dist/
npm run build:dev # tsc only
npm run build:types # declarations
CI: GitHub Actions matrix (Bun + Deno), tests split by concern.
Rules
- No comments in code
- No helper/utility files
- No Node.js-specific APIs
- Test behavior, not implementation
- Do not test what the compiler verifies