How to Set Up Local Development with Supabase and Vite for awesome-gpt-image-2
To set up local development with Supabase and Vite, configure environment variables split between browser-exposed and server-only secrets, start the local Supabase container with supabase start, and run the Vite dev server which proxies API requests to a local Node process.
Setting up local development with Supabase and Vite for the awesome-gpt-image-2 project requires orchestrating a React frontend bundled by Vite, a local Supabase PostgreSQL instance, and server-side API handlers that bypass Row-Level Security. This architecture uses environment variable prefixes to safely expose configuration to the browser while keeping sensitive service-role keys server-side according to the repository source code.
Configure Environment Variables for Local Development
The project relies on a strict separation between variables exposed to the browser and those kept server-side.
Create a local environment file by copying the template:
cp .env.example .env
Edit .env to include values provided by the local Supabase CLI:
# Browser-exposed variables (VITE_ prefix required)
VITE_SUPABASE_URL=http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY=your-anon-key
# Server-only secrets (never exposed to browser)
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
SUPER_ADMIN_EMAILS=you@example.com
Vite automatically loads .env files and injects any variable prefixed with VITE_ into the browser build via import.meta.env. Variables without this prefix remain available only to the Node process handling API requests, as implemented in vite.config.js.
Start the Local Supabase Instance
The database layer runs inside Docker containers managed by the Supabase CLI, providing Postgres, Auth, and Storage services locally.
Install the CLI globally and initialize the local stack:
npm install -g supabase
supabase start
The supabase start command automatically applies migrations found in supabase/migrations/, including schema definitions for user credits, membership plans, and Alipay integrations defined in files like 202605090001_user_credits.sql. After the containers initialize, the CLI outputs a public URL and anonymous key—paste these values into your .env file as VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.
Launch the Vite Development Server with API Proxy
Unlike standard Vite setups, this project requires the scripts/vite-local-api.mjs proxy to handle server-side API routes locally.
Start the full development stack:
npm install
npm run dev
The npm run dev command executes node scripts/vite-local-api.mjs, which performs three critical actions:
- Spawns a Node API server on a random available port, passing all server-side environment variables including
SUPABASE_SERVICE_ROLE_KEY - Configures Vite to proxy any request matching
/api/*to this local Node server - Maintains hot-module replacement for the React frontend while keeping API routes functional
You can verify the proxy works by navigating to http://localhost:5173/api/me—this should return the current Supabase user payload by hitting the api/me.js handler.
Connect the Frontend to Supabase
The browser-side Supabase client reads the injected environment variables to authenticate and query the database.
In src/supabaseClient.js, the client initialization uses createClient from @supabase/supabase-js:
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 supabase = createClient(supabaseUrl, supabaseAnonKey);
export async function getCurrentUser() {
const { data, error } = await supabase.auth.getUser();
if (error) throw error;
return data.user;
}
This client handles authentication and public database queries subject to Row-Level Security policies. Import this module into any UI component—such as src/community.jsx—to interact with Auth or fetch data using the anon key.
Implement Server-Side API Handlers
Privileged operations that bypass Row-Level Security—such as creating user credits or handling Stripe webhooks—run in the api/ folder using a service-role client.
The server-side Supabase initialization in api/_lib/supabase.js uses the restricted key:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.VITE_SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
);
export default supabase;
Service-role keys bypass all security policies, enabling administrative functions like RPC calls and table mutations. Keep these keys out of the browser by ensuring they lack the VITE_ prefix and are only referenced in server-side files under the api/ directory.
When the frontend calls /api/favorites, Vite's proxy forwards the request to the local Node process executing api/favorites.js, maintaining parity with the production Vercel deployment structure.
Summary
- Environment split: Use
VITE_*prefixes for browser variables and plainSUPABASE_*for server secrets in.env - Database startup: Run
supabase startto launch Postgres and Auth containers with automatic migration execution fromsupabase/migrations/ - Dev server: Execute
npm run devto runscripts/vite-local-api.mjs, which starts both the Vite frontend and the Node API proxy - Client setup: Import from
src/supabaseClient.jsto use the anon-key client restricted by Row-Level Security - Server setup: Use
api/_lib/supabase.jswith the service-role key for privileged operations requiring RLS bypass
Frequently Asked Questions
What is the difference between VITE_SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY?
VITE_SUPABASE_ANON_KEY is a public key safe for browser exposure that respects Row-Level Security policies, while SUPABASE_SERVICE_ROLE_KEY is a secret administrative key kept server-side in api/_lib/supabase.js that bypasses all security restrictions. Never expose the service-role key to the frontend, as it grants full database access regardless of policies.
How do I run database migrations when setting up local Supabase development?
When you execute supabase start, the CLI automatically runs all SQL files in supabase/migrations/ against the local Postgres container. Migrations define tables, functions, and security policies. If you modify schema files, stop the container with supabase stop and restart to reapply migrations, or use supabase db reset for a clean slate.
Can I set up local development with Supabase and Vite without Docker?
No. The Supabase local development workflow requires Docker to run Postgres, GoTrue (Auth), and other services. The supabase CLI orchestrates these containers automatically. Without Docker, you would need to connect to a remote Supabase project instead of running supabase start locally.
Why does the Vite setup use a proxy script instead of standard API routes?
The scripts/vite-local-api.mjs proxy allows the frontend to call /api/* endpoints exactly as it would in production on Vercel, while actually running a local Node server during development. This maintains URL parity between environments and ensures server-side code can access private environment variables like SUPABASE_SERVICE_ROLE_KEY without exposing them through Vite's client-side bundling process.
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 →