Skip to main content
RapidDev - Software Development Agency
supabase-tutorial

How to Set Environment Variables in Supabase

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.

What you'll learn

  • Where to find your Supabase API keys in the Dashboard
  • The critical difference between the anon key and the service role key
  • How to configure environment variables for different frameworks
  • How to set secrets for Supabase Edge Functions
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read10-15 minSupabase (all plans), @supabase/supabase-js v2+, Next.js/Vite/ExpoMarch 2026RapidDev Engineering Team
TL;DR

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

1

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.

typescript
1# Your Supabase environment variables:
2SUPABASE_URL=https://abcdefgh.supabase.co
3SUPABASE_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.

2

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

typescript
1# .env.local (Next.js)
2
3# Client-side (available in browser)
4NEXT_PUBLIC_SUPABASE_URL=https://abcdefgh.supabase.co
5NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
6
7# 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.

3

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.

typescript
1# .env.local (Vite / Lovable / V0)
2
3# Client-side (available in browser)
4VITE_SUPABASE_URL=https://abcdefgh.supabase.co
5VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
6
7# Usage in code:
8# const supabase = createClient(
9# import.meta.env.VITE_SUPABASE_URL,
10# import.meta.env.VITE_SUPABASE_ANON_KEY
11# )

Expected result: Your Vite-based project accesses Supabase keys through import.meta.env with the VITE_ prefix.

4

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.

typescript
1# Set a secret for Edge Functions
2supabase secrets set STRIPE_SECRET_KEY=sk_live_abcdef123456
3
4# Set multiple secrets from a file
5supabase secrets set --env-file ./supabase/.env
6
7# List current secrets
8supabase secrets list
9
10# Unset a secret
11supabase secrets unset STRIPE_SECRET_KEY
12
13# 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.

5

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.

typescript
1import { createClient } from '@supabase/supabase-js'
2
3// Client-side: uses anon key, respects RLS
4export const supabase = createClient(
5 process.env.NEXT_PUBLIC_SUPABASE_URL!,
6 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
7)
8
9// Server-side only: uses service role key, bypasses RLS
10// 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

supabase-env-setup.ts
1// Complete environment variable setup for Supabase with Next.js
2// File: src/lib/supabase.ts
3
4import { createClient, SupabaseClient } from '@supabase/supabase-js'
5
6// ============================================
7// Client-side Supabase client
8// Uses the anon key — safe for browser code
9// Respects Row Level Security policies
10// ============================================
11export const supabase: SupabaseClient = createClient(
12 process.env.NEXT_PUBLIC_SUPABASE_URL!,
13 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
14)
15
16// ============================================
17// Server-side admin client
18// Uses the service role key — NEVER expose to browser!
19// Bypasses all RLS policies
20// Only import this in:
21// - API routes
22// - Server components
23// - Middleware
24// - Cron jobs / webhooks
25// ============================================
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 }
33
34 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}
45
46// ============================================
47// Environment variable reference:
48//
49// .env.local:
50// NEXT_PUBLIC_SUPABASE_URL=https://abcdefgh.supabase.co
51// 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=value
56// 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.

ChatGPT Prompt

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.

Supabase Prompt

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.