# How the Frontend Detects the Backend Port and Configures the API Proxy

> Learn how the Next.js frontend detects the backend port using NEXT_PUBLIC_API_URL and configures an API proxy for seamless requests to your backend service.

- Repository: [FreeU-group/lifetrace](https://github.com/freeu-group/lifetrace)
- Tags: internals
- Published: 2026-03-02

---

**The Next.js frontend reads the `NEXT_PUBLIC_API_URL` environment variable (defaulting to `http://localhost:8100`) and parses it to create rewrite rules that proxy `/api/*` and `/assets/*` requests to the backend, while also configuring image remote patterns to allow loading assets from the detected port.**

In the `freeu-group/lifetrace` repository, the frontend application automatically adapts to any backend port without hard-coding values. This dynamic detection happens at build-time in [`free-todo-frontend/next.config.ts`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/next.config.ts), where environment variables are parsed to set up API proxying and image loading rules.

## Environment-Based Backend Detection

The configuration begins by reading the `NEXT_PUBLIC_API_URL` environment variable. If this variable is undefined, the system falls back to `http://localhost:8100` to support local development.

The URL is then parsed using the standard JavaScript `URL` class to extract the **protocol**, **hostname**, and **port**:

```typescript
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8100";
const apiUrl = new URL(API_BASE_URL);

```

This `apiUrl` object provides structured access to the backend's network location, allowing the frontend to reference the correct port in multiple configuration contexts without duplicating parsing logic.

## Proxying API Requests with Rewrites

The `rewrites()` function in [`next.config.ts`](https://github.com/freeu-group/lifetrace/blob/main/next.config.ts) creates proxy rules that forward frontend requests to the detected backend address. This eliminates cross-origin issues during development and unifies the API surface under the same origin as the frontend.

The implementation returns an array mapping source paths to the full backend destination:

```typescript
async function rewrites() {
  return [
    {
      source: "/api/:path*",
      destination: `${API_BASE_URL}/api/:path*`,
    },
    {
      source: "/assets/:path*",
      destination: `${API_BASE_URL}/assets/:path*`,
    },
  ];
}

```

When a request hits `/api/users`, Next.js proxies it to `${API_BASE_URL}/api/users`, preserving the port specified in `NEXT_PUBLIC_API_URL`.

## Configuring Image Loading for the Backend Port

To enable `next/image` to load images served by the backend API, the configuration defines `remotePatterns` using the parsed URL components. This ensures that images hosted on the backend's specific port are treated as safe, optimized sources.

The image configuration extracts the protocol (stripping the trailing colon), hostname, and port from the previously parsed `apiUrl`:

```typescript
const images = {
  remotePatterns: [
    {
      protocol: apiUrl.protocol.replace(":", "") as "http" | "https",
      hostname: apiUrl.hostname,
      port: apiUrl.port || undefined,
      pathname: "/api/**",
    },
  ],
};

```

If the backend runs on a non-standard port (e.g., `8100`), the `port` field ensures the image loader targets the correct server. When using standard ports (80 for HTTP, 443 for HTTPS), the field remains `undefined` to allow default behavior.

## Complete Configuration Example

Here is the consolidated configuration from [`free-todo-frontend/next.config.ts`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/next.config.ts) that ties together detection, proxying, and image loading:

```typescript
// free-todo-frontend/next.config.ts
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8100";
const apiUrl = new URL(API_BASE_URL);

/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: "/api/:path*",
        destination: `${API_BASE_URL}/api/:path*`,
      },
      {
        source: "/assets/:path*",
        destination: `${API_BASE_URL}/assets/:path*`,
      },
    ];
  },
  images: {
    remotePatterns: [
      {
        protocol: apiUrl.protocol.replace(":", "") as "http" | "https",
        hostname: apiUrl.hostname,
        port: apiUrl.port || undefined,
        pathname: "/api/**",
      },
    ],
  },
};

module.exports = nextConfig;

```

This setup ensures that whether the backend runs on the default port `8100` or a custom port specified via environment variable, the frontend correctly routes API calls and displays backend-hosted images without additional code changes.

## Summary

- The frontend detects the backend port by reading `NEXT_PUBLIC_API_URL` and falling back to `http://localhost:8100` if undefined.
- The `URL` class parses the environment variable to extract protocol, hostname, and port for reuse across configuration objects.
- Rewrite rules in [`next.config.ts`](https://github.com/freeu-group/lifetrace/blob/main/next.config.ts) proxy `/api/*` and `/assets/*` paths to the full backend URL, including the detected port.
- Image remote patterns are dynamically configured to allow `next/image` to load assets from the backend's specific protocol and port combination.
- All configuration logic resides in [`free-todo-frontend/next.config.ts`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/next.config.ts), making the setup maintainable and environment-agnostic.

## Frequently Asked Questions

### What happens if `NEXT_PUBLIC_API_URL` is not set?

If the environment variable is undefined, the configuration defaults to `http://localhost:8100`. This ensures the development server starts correctly without manual configuration, assuming the backend runs on the standard port defined in the project documentation.

### How do I change the backend port in development?

Create a `.env.local` file in `free-todo-frontend/` and set `NEXT_PUBLIC_API_URL=http://localhost:YOUR_PORT`. Because the variable uses the `NEXT_PUBLIC_` prefix, it is embedded at build-time and becomes available to the browser-side code for image loading configuration.

### Why does the frontend need to proxy `/assets/*` requests?

The backend serves static files and uploaded assets from its `/assets/` endpoint. By proxying these requests through the Next.js frontend, the application avoids cross-origin resource sharing (CORS) complications and maintains consistent URL structures between development and production environments.

### Does this configuration support HTTPS backends?

Yes. The `URL` parser automatically detects `https://` protocols from `NEXT_PUBLIC_API_URL`. The protocol is passed to both the rewrite destinations (as part of `API_BASE_URL`) and the image remote patterns (after stripping the colon), allowing secure connections to production backends.