Supabase projects have two main API keys: the anon key (safe for client-side, respects RLS) and the service role key (server-only, bypasses RLS). Find both in Dashboard > Settings > API. For local development, store them in .env.local. For Edge Functions, use supabase secrets set. Each frontend framework has its own prefix: NEXT_PUBLIC_ for Next.js, VITE_ for Vite/Lovable/V0, and EXPO_PUBLIC_ for Expo.
Setting Environment Variables for Supabase Projects
Every Supabase project requires two environment variables to connect: the project URL and an API key. Understanding which key to use where is critical for security. The anon key is designed for client-side code and respects Row Level Security policies. The service role key bypasses all security and must only be used in server-side code. This tutorial shows you where to find these keys, how to configure them for your framework, and how to manage secrets for Edge Functions.
Prerequisites
- A Supabase project created in the Dashboard
- A frontend project using Next.js, Vite, React, or another framework
- Basic understanding of environment variables and .env files
Step-by-step guide
Find your API keys in the Supabase Dashboard
Find your API keys in the Supabase Dashboard
Go to the Supabase Dashboard, select your project, and navigate to Settings > API. You will see two sections: Project URL and Project API keys. The Project URL is your Supabase endpoint (e.g., https://abcdefgh.supabase.co). Under API keys, you have the anon (public) key and the service_role (secret) key. The anon key is safe to use in browser code because it respects RLS policies. The service role key bypasses all RLS and should never be exposed in client-side code.
1# Your Supabase environment variables:2SUPABASE_URL=https://abcdefgh.supabase.co3SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...4SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Expected result: You have copied your project URL, anon key, and service role key from the Dashboard.
Configure environment variables for Next.js
Configure environment variables for Next.js
Next.js uses .env.local for local development environment variables. Variables prefixed with NEXT_PUBLIC_ are exposed to the browser. The Supabase URL and anon key need this prefix because the client runs in the browser. The service role key must NOT have the NEXT_PUBLIC_ prefix because it should only be available in server-side code (API routes, server components, middleware).
1# .env.local (Next.js)23# Client-side (available in browser)4NEXT_PUBLIC_SUPABASE_URL=https://abcdefgh.supabase.co5NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...67# Server-side only (NOT exposed to browser)8SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Expected result: Your Next.js project reads Supabase keys from .env.local with proper NEXT_PUBLIC_ prefixing.
Configure environment variables for Vite, Lovable, and V0
Configure environment variables for Vite, Lovable, and V0
Vite-based projects (including Lovable and V0 exports) use the VITE_ prefix for client-side variables. Only variables starting with VITE_ are available in browser code via import.meta.env. For Lovable projects, set environment variables in the Cloud tab > Secrets section. For V0 projects, set them in the Vars panel. When deploying to Vercel, use the Supabase integration or manually add the variables in Vercel's Environment Variables settings.
1# .env.local (Vite / Lovable / V0)23# Client-side (available in browser)4VITE_SUPABASE_URL=https://abcdefgh.supabase.co5VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...67# Usage in code:8# const supabase = createClient(9# import.meta.env.VITE_SUPABASE_URL,10# import.meta.env.VITE_SUPABASE_ANON_KEY11# )Expected result: Your Vite-based project accesses Supabase keys through import.meta.env with the VITE_ prefix.
Set secrets for Supabase Edge Functions
Set secrets for Supabase Edge Functions
Edge Functions automatically have access to SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, and SUPABASE_DB_URL without any configuration. For additional secrets (like third-party API keys), use the supabase secrets set command. Secrets are encrypted and available via Deno.env.get() inside your functions. You do not need to redeploy functions after setting new secrets.
1# Set a secret for Edge Functions2supabase secrets set STRIPE_SECRET_KEY=sk_live_abcdef12345634# Set multiple secrets from a file5supabase secrets set --env-file ./supabase/.env67# List current secrets8supabase secrets list910# Unset a secret11supabase secrets unset STRIPE_SECRET_KEY1213# Access in Edge Function code:14# const stripeKey = Deno.env.get('STRIPE_SECRET_KEY')!Expected result: Edge Function secrets are set and accessible via Deno.env.get() without redeploying.
Initialize the Supabase client with environment variables
Initialize the Supabase client with environment variables
With environment variables configured, create your Supabase client. For client-side code, use the anon key. For server-side code that needs to bypass RLS (admin operations, webhooks, cron jobs), use the service role key. Always create separate client instances for each purpose so you do not accidentally use the service role key in browser code.
1import { createClient } from '@supabase/supabase-js'23// Client-side: uses anon key, respects RLS4export const supabase = createClient(5 process.env.NEXT_PUBLIC_SUPABASE_URL!,6 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!7)89// Server-side only: uses service role key, bypasses RLS10// NEVER import this in client-side code!11export const supabaseAdmin = createClient(12 process.env.NEXT_PUBLIC_SUPABASE_URL!,13 process.env.SUPABASE_SERVICE_ROLE_KEY!,14 {15 auth: {16 autoRefreshToken: false,17 persistSession: false,18 },19 }20)Expected result: Separate Supabase clients are configured for client-side (anon key) and server-side (service role key) usage.
Complete working example
1// Complete environment variable setup for Supabase with Next.js2// File: src/lib/supabase.ts34import { createClient, SupabaseClient } from '@supabase/supabase-js'56// ============================================7// Client-side Supabase client8// Uses the anon key — safe for browser code9// Respects Row Level Security policies10// ============================================11export const supabase: SupabaseClient = createClient(12 process.env.NEXT_PUBLIC_SUPABASE_URL!,13 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!14)1516// ============================================17// Server-side admin client18// Uses the service role key — NEVER expose to browser!19// Bypasses all RLS policies20// Only import this in:21// - API routes22// - Server components23// - Middleware24// - Cron jobs / webhooks25// ============================================26export function createAdminClient(): SupabaseClient {27 if (typeof window !== 'undefined') {28 throw new Error(29 'createAdminClient must only be called on the server. ' +30 'The service role key bypasses RLS and must never be exposed to the browser.'31 )32 }3334 return createClient(35 process.env.NEXT_PUBLIC_SUPABASE_URL!,36 process.env.SUPABASE_SERVICE_ROLE_KEY!,37 {38 auth: {39 autoRefreshToken: false,40 persistSession: false,41 },42 }43 )44}4546// ============================================47// Environment variable reference:48//49// .env.local:50// NEXT_PUBLIC_SUPABASE_URL=https://abcdefgh.supabase.co51// NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...52// SUPABASE_SERVICE_ROLE_KEY=eyJhbGci...53//54// Edge Functions (set via CLI):55// supabase secrets set MY_SECRET_KEY=value56// Access: Deno.env.get('MY_SECRET_KEY')57// ============================================Common mistakes when setting Environment Variables in Supabase
Why it's a problem: Using the service role key in client-side code, exposing it to all users
How to avoid: Only use the service role key in server-side code (API routes, server components, Edge Functions). Use the anon key for all client-side Supabase operations.
Why it's a problem: Committing .env.local files to version control, leaking API keys
How to avoid: Add .env.local and .env to your .gitignore file. Use environment variable management in your deployment platform (Vercel, Netlify) for production.
Why it's a problem: Using the wrong prefix for the framework (e.g., NEXT_PUBLIC_ in a Vite project)
How to avoid: Use NEXT_PUBLIC_ for Next.js, VITE_ for Vite/Lovable/V0, EXPO_PUBLIC_ for Expo, and REACT_APP_ for Create React App. Only variables with the correct prefix are available in browser code.
Why it's a problem: Not setting SUPABASE_SERVICE_ROLE_KEY without NEXT_PUBLIC_ prefix, making it available in the browser
How to avoid: Never prefix the service role key with NEXT_PUBLIC_ or VITE_. It should only be accessible in server-side code.
Best practices
- Always use the anon key for client-side code and the service role key only in server-side code
- Store environment variables in .env.local for development and in your deployment platform for production
- Add .env.local to .gitignore to prevent committing secrets to version control
- Use the correct framework prefix: NEXT_PUBLIC_ (Next.js), VITE_ (Vite), EXPO_PUBLIC_ (Expo)
- Create separate Supabase client instances for client-side and server-side admin operations
- For Edge Functions, use supabase secrets set instead of hardcoding values in function code
- Add a runtime check in your admin client to prevent it from being used in browser code
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to set up Supabase environment variables for a Next.js project. Show me where to find my API keys, how to configure .env.local with proper NEXT_PUBLIC_ prefixing, how to create separate client and admin Supabase clients, and how to set secrets for Edge Functions.
Create a Supabase client configuration module for Next.js that exports a browser-safe client using the anon key and a server-only admin client using the service role key. Include a runtime check that throws an error if the admin client is accidentally used in browser code.
Frequently asked questions
What is the difference between the anon key and the service role key?
The anon key creates requests with the anon PostgreSQL role and respects all Row Level Security policies. It is safe for client-side code. The service role key bypasses all RLS policies and has full access to the database. It must only be used in server-side code.
Can I regenerate my Supabase API keys?
You can reset your database password in Dashboard > Settings > Database. The API keys (anon and service role) are derived from your JWT secret and cannot be individually regenerated without changing the JWT secret, which invalidates all existing sessions.
Do Supabase Edge Functions automatically have access to my API keys?
Yes. Edge Functions automatically have access to SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, and SUPABASE_DB_URL without any configuration. You only need to use supabase secrets set for additional third-party secrets.
How do I set environment variables in Lovable?
In Lovable, click the Cloud tab (click the + button next to the Preview panel), then go to the Secrets section. Enter your key-value pairs there. Lovable encrypts and injects them into your project automatically.
Should I use the anon key or service role key for server-side rendering?
Use the anon key with the user's session token for SSR. The session token authenticates the request as the user, and RLS policies apply. Only use the service role key for admin operations that need to bypass RLS, like creating users or accessing all records.
What happens if I accidentally expose the service role key?
If the service role key is leaked, anyone can bypass all RLS policies and access or modify all data in your database. Immediately rotate the JWT secret in Dashboard > Settings > API and update all server-side code with the new keys. All existing sessions will be invalidated.
Can RapidDev help secure my Supabase environment configuration?
Yes. RapidDev can audit your environment variable configuration, ensure API keys are not exposed in client-side code, set up proper secret management for Edge Functions, and configure deployment platforms with the correct variables.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation