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

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, 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:

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

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:

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 that ties together detection, proxying, and image loading:

// 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 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, 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →