How to Set Up Supabase Authentication in awesome-gpt-image-2: Client and Server Configuration
Configure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in your environment, then initialize the browser client via src/supabaseClient.js and protect API routes using the server-side helpers exported from api/_lib/supabase.js.
The awesome-gpt-image-2 repository by freestylefly implements a split authentication architecture that handles user sessions in the browser while verifying identities on the server. This guide walks you through wiring up the Supabase JavaScript client, setting the required environment variables, and securing your API endpoints using the built-in authentication helpers.
Configure Environment Variables
Create a .env file at the repository root based on the provided template. The project requires two client-side variables and one optional server-side variable:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-public-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-secret
The VITE_ prefix allows Vite to expose these variables to the client bundle via import.meta.env. The SUPABASE_SERVICE_ROLE_KEY bypasses Row Level Security and should never reach the browser; it is used exclusively by serverless functions.
Initialize the Browser Client
The file src/supabaseClient.js bootstraps the Supabase client for the React frontend. It validates that both environment variables exist before calling createClient to prevent runtime crashes in unconfigured environments.
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
export const isSupabaseConfigured = Boolean(supabaseUrl && supabaseAnonKey);
export const supabase = isSupabaseConfigured
? createClient(supabaseUrl, supabaseAnonKey, {
auth: {
autoRefreshToken: true,
detectSessionInUrl: true,
persistSession: true,
},
})
: null;
Key features of this configuration:
- autoRefreshToken automatically refreshes the JWT before it expires.
- detectSessionInUrl captures the session hash when users return from external OAuth providers.
- persistSession stores the session in
localStoragefor continuity across page reloads.
Set Up Server-Side Authentication
Serverless API routes import helpers from api/_lib/supabase.js to validate incoming requests and perform administrative actions. This module exports three critical functions:
getAuthContext(req)extracts the JWT from theAuthorizationheader or cookie, validates it against Supabase, and returns an object containinguserandsession.getSupabaseAdminClient()returns a privileged Supabase client initialized withSUPABASE_SERVICE_ROLE_KEY. Use this client only for internal operations that require bypassing security policies.isSupabaseServerConfigured()verifies that the service role key is present before attempting to create the admin client.
Example usage inside an API route:
import { getAuthContext, getSupabaseAdminClient } from '../_lib/supabase.js';
export default async function handler(req, res) {
const { user } = await getAuthContext(req);
if (!user) {
return res.status(401).json({ error: 'unauthenticated' });
}
const adminClient = getSupabaseAdminClient();
// Perform privileged operations here
}
Secure API Routes
The repository protects sensitive endpoints—such as api/me.js, api/generation/status.js, and the api/billing routes—by invoking getAuthContext at the top of each handler. This pattern ensures that only valid Supabase sessions can access user-specific data or trigger credit-consuming operations.
const { user } = await getAuthContext(req);
if (!user) return res.status(401).json({ error: 'unauthenticated' });
If the JWT is near expiration, the server-side validation automatically coordinates with the client-side refresh logic, maintaining a seamless user experience.
Implement Authentication in the UI
With the client initialized, React components can trigger OAuth flows and retrieve the current user. The following example initiates a Google sign-in:
import { supabase } from './supabaseClient';
async function signInWithGoogle() {
const { error } = await supabase.auth.signInWithOAuth({
provider: 'google'
});
if (error) console.error('Auth error:', error);
}
After successful authentication, retrieve the user object anywhere in your component tree:
const { data: { user } } = await supabase.auth.getUser();
Summary
- Environment setup requires
VITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEYfor the browser, plusSUPABASE_SERVICE_ROLE_KEYfor server-side admin tasks. - Client initialization happens in
src/supabaseClient.js, which exportsisSupabaseConfiguredand acreateClientinstance with automatic token refresh and session persistence. - Server helpers in
api/_lib/supabase.jsprovidegetAuthContextfor request validation andgetSupabaseAdminClientfor privileged database access. - API protection is implemented by destructuring
userfromgetAuthContextand returning a 401 response when authentication is missing. - UI integration uses the exported
supabaseclient to initiate OAuth flows and fetch the current session.
Frequently Asked Questions
What environment variables are required for Supabase authentication in this project?
You must define VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY for the client to function. For server-side operations that bypass Row Level Security, add SUPABASE_SERVICE_ROLE_KEY. All variables are listed in .env.example at the repository root.
How does the server verify the JWT token from the client?
The getAuthContext function in api/_lib/supabase.js extracts the token from the Authorization header or cookie and validates it against the Supabase Auth API. It returns the authenticated user object or null if the token is invalid or expired.
What is the difference between the anon key and the service role key?
The anon key (used in src/supabaseClient.js) is a public identifier that respects Row Level Security policies. The service role key (used in getSupabaseAdminClient()) is a secret key that grants full database access and must never be exposed to the browser.
How do I check if Supabase is configured before initializing the client?
Import isSupabaseConfigured from src/supabaseClient.js. This boolean evaluates to true only when both VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are present, allowing you to conditionally render authentication UI or skip Supabase-dependent logic during development.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →