# How to Locally Develop the React Frontend with Vercel API Proxy in awesome‑gpt‑image‑2

> Learn to locally develop your React frontend with Vercel API proxy using awesome-gpt-image-2. This guide simplifies backend integration with dynamic serverless handler imports.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-09-01

---

**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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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:

```javascript
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:

1. **Parse the URL** using `new URL(req.url, 'http://127.0.0.1')`
2. **Lookup the route** in `routeLoaders`
3. **Short‑circuit unconfigured community routes** — if Supabase is missing, `/api/community/status` returns a canned 200 response (lines 71‑80)
4. **Inject request helpers** — attaches `req.query`, `x-forwarded-proto` header, and response methods ([`res.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/res.json), `res.send`, `res.redirect`)
5. **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

```bash
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:

```bash
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

```bash
npm run dev

```

The server initializes at `http://localhost:5173`. Vite loads [`vite.config.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/vite.config.js), which imports and registers the `localVercelApi` plugin before the React plugin:

```javascript
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:

```javascript
fetch('/api/community/status')
  .then(r => r.json())
  .then(console.log);

```

Without Supabase configured, expect this response defined in the plugin's fallback logic:

```json
{
  "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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/vite.config.js) is needed—the plugin handles routing internally.

### 6. Test Production Build (Optional)

When ready to validate the static output:

```bash
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:

```javascript
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) polyfills `res.json()`, `res.send()`, and `res.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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) or your own components:

```javascript
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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/vite.config.js) | Vite configuration with `localVercelApi()` plugin registration |
| `scripts/vite-local-api.mjs` | Middleware implementation for local API proxy |
| [`api/community/status.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/community/status.js) | Example serverless handler; loaded dynamically in dev |
| [`api/community/config.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/community/config.js) | Configuration endpoint handler |
| [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) | React entry point making API calls |
| `.env.example` | Required environment variable documentation |
| [`vercel.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/vercel.json) | Production Vercel configuration (reference only) |

## Summary

- **The `localVercelApi` Vite 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.mjs` maps `/api/*` paths to local handlers in the `api/` directory using lazy `import()` calls.
- **Dev‑only activation** via `apply: 'serve'` ensures zero impact on production builds; `npm run build` outputs a static bundle ready for Vercel's real serverless functions.
- **Zero additional configuration** is needed beyond `npm install`, environment variables, and `npm 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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/vercel.json)—handles API routes.