@tuturuuu/supabase
v0.4.0
Published
Supabase client and utilities for Next.js applications with SSR support, cookie handling, and TypeScript type safety
Maintainers
Readme
@tuturuuu/supabase
Supabase client and utilities for Next.js applications with SSR support, cookie handling, and TypeScript type safety.
Features
- 🚀 Next.js Optimized: Built specifically for Next.js 16+ with App Router support
- 🔒 SSR-Safe: Proper server-side rendering with cookie-based authentication
- 🎯 Type-Safe: Full TypeScript support with generated database types
- 🔄 Realtime: Built-in realtime subscription utilities
- 👤 User Management: Helper functions for user operations
- 🛡️ Secure: Admin client for server-side operations with service key
Installation
npm install @tuturuuu/supabase
# or
yarn add @tuturuuu/supabase
# or
pnpm add @tuturuuu/supabase
# or
bun add @tuturuuu/supabasePeer Dependencies
This package requires the following peer dependencies:
next>= 15.0.0react>= 18.0.0react-dom>= 18.0.0
Environment Variables
Set the following environment variables in your .env.local or .env file:
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-supabase-anon-key
SUPABASE_SECRET_KEY=your-service-role-key # For admin operations onlyUsage
Client-Side (Browser)
Use in Client Components for browser-side operations:
'use client';
import { createClient } from '@tuturuuu/supabase/next/client';
export default function ClientComponent() {
const supabase = createClient();
// Use the client for queries
const { data, error } = await supabase
.from('your_table')
.select('*');
return <div>{/* Your component */}</div>;
}Server-Side (Server Components & Actions)
Use in Server Components and Server Actions:
import { createClient } from '@tuturuuu/supabase/next/server';
export default async function ServerComponent() {
const supabase = await createClient();
const { data, error } = await supabase
.from('your_table')
.select('*');
return <div>{/* Your component */}</div>;
}Admin Client (Server-Only)
For server-side operations that require service role privileges:
import { createAdminClient } from '@tuturuuu/supabase/next/server';
// In API routes or Server Actions
export async function serverAction() {
const adminClient = await createAdminClient();
// Bypass RLS policies
const { data, error } = await adminClient
.from('your_table')
.select('*');
return data;
}User Utilities
Helper functions for common user operations:
import { getUser, getCurrentUser } from '@tuturuuu/supabase/next/user';
// Get authenticated user (returns null if not authenticated)
const user = await getUser();
// Get authenticated user (throws error if not authenticated)
const user = await getCurrentUser();Realtime Subscriptions
Subscribe to realtime database changes:
'use client';
import { createClient } from '@tuturuuu/supabase/next/client';
import { useEffect } from 'react';
export default function RealtimeComponent() {
useEffect(() => {
const supabase = createClient();
const channel = supabase
.channel('table-changes')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'your_table'
}, (payload) => {
console.log('Change received!', payload);
})
.subscribe();
return () => {
channel.unsubscribe();
};
}, []);
return <div>{/* Your component */}</div>;
}API Proxy
Proxy requests through your API routes for enhanced security:
import { createProxyClient } from '@tuturuuu/supabase/next/proxy';
// In your API route
export async function POST(request: Request) {
const supabase = await createProxyClient(request);
// Use the client
const { data, error } = await supabase
.from('your_table')
.select('*');
return Response.json({ data, error });
}API Reference
createClient()
Creates a Supabase client for browser-side operations.
Returns: SupabaseClient<Database>
createClient() (Server)
Creates a Supabase client for server-side operations with cookie handling.
Returns: Promise<SupabaseClient<Database>>
createAdminClient(options?)
Creates a Supabase admin client with service role privileges.
Options:
noCookie?: boolean- Disable cookie handling (default: false)
Returns: Promise<SupabaseClient<Database>>
getUser()
Gets the currently authenticated user, returns null if not authenticated.
Returns: Promise<User | null>
getCurrentUser()
Gets the currently authenticated user, throws error if not authenticated.
Returns: Promise<User>
Throws: Error if user is not authenticated
createProxyClient(request)
Creates a Supabase client from an incoming request for API proxying.
Parameters:
request: Request- The incoming request object
Returns: Promise<SupabaseClient<Database>>
TypeScript
This package is written in TypeScript and includes type definitions. For best experience, generate types from your Supabase schema:
# If using Supabase CLI
npx supabase gen types typescript --project-id your-project-id > types/supabase.tsThen use them with your client:
import type { Database } from './types/supabase';
import { createClient } from '@tuturuuu/supabase/next/client';
const supabase = createClient<Database>();Best Practices
Client vs Server: Always use the appropriate client creation function:
- Browser:
createClient()from/next/client - Server:
createClient()from/next/server - Admin:
createAdminClient()from/next/server
- Browser:
Security: Never expose the service role key in client-side code. Use
createAdminClient()only in server-side contexts.Error Handling: Always check for errors when making Supabase queries:
const { data, error } = await supabase.from('table').select('*'); if (error) { console.error('Error:', error); return; }Realtime Cleanup: Always unsubscribe from realtime channels to prevent memory leaks:
useEffect(() => { const channel = supabase.channel('my-channel'); // ... subscription setup return () => channel.unsubscribe(); }, []);
Development
Monorepo Development
Important: This package must be built before it can be used by other packages in the monorepo.
Note for New Contributors: After cloning the repository or switching branches, you must build this package first. The
dist/folder is git-ignored and won't be present until you build it.
# Install dependencies
bun install
# Build the package (required before first use)
bun run build
# Run tests
bun run test
# Type check
bun run type-check
# Clean build artifacts
bun run cleanWatch Mode (During Active Development)
If you're actively working on this package, you can set up watch mode:
# Terminal 1: Watch and rebuild on changes
bun run dev
# Terminal 2: Run your app that depends on this package
cd ../../apps/web
bun devMonorepo Build Order
When building the entire monorepo, this package should be built before dependent packages:
# From monorepo root
bun run build # Turborepo handles the correct build orderContributing
Contributions are welcome! Please read our Contributing Guide for details.
License
MIT © Tuturuuu
