fix(frontend): resolve API base URL at request time for production

Use same-origin /api in the browser so builds are not stuck with baked-in
localhost. Server-side fetches use INTERNAL_API_URL, NEXT_PUBLIC_API_URL, or
loopback. Centralize logic in lib/api-base.ts.

Made-with: Cursor
This commit is contained in:
Michilis
2026-04-01 19:52:54 +00:00
parent 76210db03d
commit 8cdf0231ce
7 changed files with 25 additions and 17 deletions

View File

@@ -1,10 +1,9 @@
import { NextRequest, NextResponse } from 'next/server';
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api';
import { apiUrl } from '@/lib/api-base';
export async function GET(req: NextRequest) {
const name = req.nextUrl.searchParams.get('name');
const upstream = new URL(`${API_URL}/nip05`);
const upstream = new URL(apiUrl('/nip05'));
if (name) upstream.searchParams.set('name', name);
const res = await fetch(upstream.toString(), { cache: 'no-store' });

View File

@@ -1,12 +1,11 @@
import type { Metadata } from "next";
import BlogPostClient from "./BlogPostClient";
import { BlogPostingJsonLd, BreadcrumbJsonLd } from "@/components/public/JsonLd";
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000/api";
import { apiUrl } from "@/lib/api-base";
async function fetchPost(slug: string) {
try {
const res = await fetch(`${apiUrl}/posts/${slug}`, {
const res = await fetch(apiUrl(`/posts/${slug}`), {
next: { revalidate: 300 },
});
if (!res.ok) return null;

View File

@@ -1,11 +1,10 @@
import { NextResponse } from 'next/server';
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api';
import { apiUrl } from '@/lib/api-base';
export async function GET() {
let upstream: Response;
try {
upstream = await fetch(`${API_URL}/calendar/ics`, {
upstream = await fetch(apiUrl('/calendar/ics'), {
headers: { Accept: 'text/calendar' },
cache: 'no-store',
});

View File

@@ -1,12 +1,11 @@
import type { Metadata } from "next";
import EventDetailClient from "./EventDetailClient";
import { EventJsonLd, BreadcrumbJsonLd } from "@/components/public/JsonLd";
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000/api";
import { apiUrl } from "@/lib/api-base";
async function fetchEvent(id: string) {
try {
const res = await fetch(`${apiUrl}/meetups/${id}`, {
const res = await fetch(apiUrl(`/meetups/${id}`), {
next: { revalidate: 300 },
});
if (!res.ok) return null;

View File

@@ -1,12 +1,12 @@
import type { MetadataRoute } from "next";
import { apiUrl } from "@/lib/api-base";
const siteUrl =
process.env.NEXT_PUBLIC_SITE_URL || "https://belgianbitcoinembassy.org";
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000/api";
async function fetchJson<T>(path: string): Promise<T | null> {
try {
const res = await fetch(`${apiUrl}${path}`, { next: { revalidate: 3600 } });
const res = await fetch(apiUrl(path), { next: { revalidate: 3600 } });
if (!res.ok) return null;
return res.json();
} catch {