How to Locally Develop the React Frontend with Vercel API Proxy in awesome‑gpt‑image‑2
The awesome‑gpt‑image‑2 repository uses a custom Vite plugin that intercepts /api/* requests during local development and dynamically imports serverless handlers from the api/ directory, eliminating the need for a separate backend or external proxy configuration.
The awesome‑gpt‑image‑2 project provides a single‑page React application that relies on Vercel serverless functions for its API layer. Developing this frontend locally presents a challenge: you need those API routes available without deploying to Vercel. According to the source code, the solution is a purpose‑built Vite plugin that runs exclusively during development and transparently proxies requests to local handler modules.
How the Vercel API Proxy Works
The local development system consists of three coordinated components that replicate Vercel's serverless runtime in your dev environment.
| Component | Purpose | Location |
|---|---|---|
| Vite configuration | Registers the custom plugin alongside React support | vite.config.js |
localVercelApi plugin |
Middleware that routes requests and provides response helpers | scripts/vite-local-api.mjs |
| API handlers | Node‑style modules exporting (req, res) functions |
api/ directory |
The Route Loading System
At the heart of scripts/vite-local-api.mjs (lines 1‑14) sits a Map called routeLoaders that lazily maps URL paths to dynamic imports:
const routeLoaders = new Map([
['/api/community/config', () => import('../api/community/config.js')],
['/api/community/status', () => import('../api/community/status.js')],
// … additional routes …
]);
This lazy‑loading design ensures that API handlers are only imported when first requested, keeping dev server startup fast.
Request Processing Pipeline
When a request hits the dev server, the middleware (lines 55‑99) executes a five‑stage pipeline:
- Parse the URL using
new URL(req.url, 'http://127.0.0.1') - Lookup the route in
routeLoaders - Short‑circuit unconfigured community routes — if Supabase is missing,
/api/community/statusreturns a canned 200 response (lines 71‑80) - Inject request helpers — attaches
req.query,x-forwarded-protoheader, and response methods (res.json,res.send,res.redirect) - Execute the handler with
await module.default(req, res)
Crucially, the plugin declares apply: 'serve', so it only activates during npm run dev. Production builds (npm run build) produce a static bundle without any proxy code—your API routes are handled by real Vercel serverless functions in deployment.
Setting Up Local Development with the Vercel API Proxy
Follow these steps to run the React frontend locally with full API support.
1. Clone and Install Dependencies
git clone https://github.com/freestylefly/awesome-gpt-image-2.git
cd awesome-gpt-image-2
npm install
This pulls React, Vite, the Supabase client, and development tooling.
2. Configure Environment Variables
Copy the example file and populate real values for your Supabase project and optional Google Analytics:
cp .env.example .env
# Edit .env to set:
# VITE_SUPABASE_URL
# SUPABASE_SERVICE_ROLE_KEY
# VITE_GA_MEASUREMENT_ID
The SUPABASE_SERVICE_ROLE_KEY is required for community API functionality; without it, the proxy returns fallback responses.
3. Start the Vite Dev Server
npm run dev
The server initializes at http://localhost:5173. Vite loads vite.config.js, which imports and registers the localVercelApi plugin before the React plugin:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { localVercelApi } from './scripts/vite-local-api.mjs';
export default defineConfig({
plugins: [localVercelApi(), react()], // API proxy must precede React
publicDir: 'data',
build: {
outDir: 'dist',
sourcemap: false
}
});
4. Verify the Proxy is Active
Open your browser console and test a community endpoint:
fetch('/api/community/status')
.then(r => r.json())
.then(console.log);
Without Supabase configured, expect this response defined in the plugin's fallback logic:
{
"ok": true,
"authenticated": false,
"eligible": false,
"qrReady": false,
"paymentEnabled": false,
"order": null,
"localPreview": true
}
This confirms the middleware is intercepting requests and routing them correctly.
5. Develop Your React Components
Edit files under src/ (e.g., src/main.jsx). The dev server provides hot module replacement, and all /api/* calls are proxied transparently. No additional proxy configuration in vite.config.js is needed—the plugin handles routing internally.
6. Test Production Build (Optional)
When ready to validate the static output:
npm run build
npm run preview
The preview server serves dist/ without the API proxy. API routes are expected to be provided by Vercel's serverless infrastructure in actual deployment.
Inside the Vite Plugin Implementation
The localVercelApi function in scripts/vite-local-api.mjs demonstrates several techniques for replicating serverless runtime behavior:
export function localVercelApi() {
return {
name: 'local-vercel-community-api',
apply: 'serve', // Dev-only: excluded from production builds
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
const requestUrl = new URL(req.url || '/', 'http://127.0.0.1');
const routeLoader = routeLoaders.get(requestUrl.pathname);
const isCommunityApi = requestUrl.pathname.startsWith('/api/community/')
|| requestUrl.pathname.startsWith('/api/admin/community/');
// 404 for unknown community routes
if (!routeLoader) {
if (isCommunityApi) {
return sendJson(res, 404, { ok: false, error: 'NOT_FOUND' });
}
return next(); // Let Vite handle static assets
}
// Supabase-less fallback for status check
if (requestUrl.pathname === '/api/community/status'
&& !isSupabaseServerConfigured()) {
return sendJson(res, 200, { /* fallback status */ });
}
// Populate Vercel-compatible request/response objects
req.query = Object.fromEntries(requestUrl.searchParams.entries());
attachVercelResponseHelpers(res);
// Invoke the handler
const module = await routeLoader();
await module.default(req, res);
});
}
};
}
Key implementation details:
attachVercelResponseHelpers(res)(lines 83‑52) polyfillsres.json(),res.send(), andres.redirect()to match Vercel's response API- Dynamic imports avoid loading all handlers upfront—only accessed routes are evaluated
- Environment detection via
isSupabaseServerConfigured()enables graceful degradation when credentials are missing
Calling API Routes from React
Any component can use standard fetch against /api/* paths. From src/main.jsx or your own components:
async function loadCommunityStatus() {
const resp = await fetch('/api/community/status');
if (!resp.ok) throw new Error(`API error: ${resp.status}`);
const data = await resp.json();
return data;
}
// Usage in a component
useEffect(() => {
loadCommunityStatus().then(setStatus);
}, []);
The browser sees these as same‑origin requests because the Vite dev server handles them internally—no CORS configuration required.
Key Files Reference
| File | Role |
|---|---|
vite.config.js |
Vite configuration with localVercelApi() plugin registration |
scripts/vite-local-api.mjs |
Middleware implementation for local API proxy |
api/community/status.js |
Example serverless handler; loaded dynamically in dev |
api/community/config.js |
Configuration endpoint handler |
src/main.jsx |
React entry point making API calls |
.env.example |
Required environment variable documentation |
vercel.json |
Production Vercel configuration (reference only) |
Summary
- The
localVercelApiVite plugin enables local development of the awesome‑gpt‑image‑2 React frontend with full API functionality—no external proxy or deployed backend required. - Dynamic route loading from
scripts/vite-local-api.mjsmaps/api/*paths to local handlers in theapi/directory using lazyimport()calls. - Dev‑only activation via
apply: 'serve'ensures zero impact on production builds;npm run buildoutputs a static bundle ready for Vercel's real serverless functions. - Zero additional configuration is needed beyond
npm install, environment variables, andnpm run dev—the plugin handles all request routing and response helper injection automatically.
Frequently Asked Questions
Do I need to deploy the API to Vercel before I can develop the frontend?
No. The localVercelApi plugin in scripts/vite-local-api.mjs intercepts all /api/* requests during npm run dev and executes the corresponding handler files from your local api/ directory. You only deploy to Vercel when you're ready for production.
What happens if I don't configure Supabase environment variables?
The plugin detects missing Supabase configuration via isSupabaseServerConfigured() and returns fallback responses for community endpoints. For example, /api/community/status returns a 200 with localPreview: true and authenticated: false, allowing UI development to proceed without a backend database.
Can I add new API routes for local development?
Yes. Create a new handler file in api/ exporting a default (req, res) function, then register its path in routeLoaders within scripts/vite-local-api.mjs. The dynamic import system will pick it up on the next request without restarting the dev server.
Why does the production build exclude the proxy?
The plugin specifies apply: 'serve', which restricts it to Vite's development server only. The npm run build command generates a static dist/ folder containing just the React application. In production, Vercel's actual serverless infrastructure—configured via vercel.json—handles API routes.
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 →