Next.js Discord

Discord Forum

Dynamically set base url for robots, webmanifest and layout?

Unanswered
Transvaal lion posted this in #help-forum
Open in Discord
Transvaal lionOP
Hey,
I'm trying to dynamically use a base url in my project so they work when using preview deployments.
For example this is my robots.ts file
import type { MetadataRoute } from "next";
import { getBaseUrl } from "@actions/utils";

const baseUrl = await getBaseUrl();
const sitemapUrl = new URL("/sitemap.xml", baseUrl).toString();

export default function robots(): MetadataRoute.Robots {
    return {
        rules: {
            userAgent: "*",
            allow: ["/", "/llms.txt"],
            disallow: ["/dashboard", "/eventsub", "/proxy", "/overlay"],
        },
        sitemap: sitemapUrl,
    };
}


The generated robots.txt file looks like this:
User-Agent: *
Allow: /
Allow: /llms.txt
Disallow: /dashboard
Disallow: /eventsub
Disallow: /proxy
Disallow: /overlay

Sitemap: http://localhost:3000/sitemap.xml (should be myPreview-x6sa389xda.domain.com)


This is my util.ts file:
"use server";

export async function isPreview() {
    return String(process.env.IS_PREVIEW).toLowerCase() === "true";
}

export async function isCoolify() {
    return Object.keys(process.env).some((key) => /^COOLIFY_/.test(key));
}

export async function getBaseUrl(): Promise<URL> {
    let url = process.env.COOLIFY_URL || "http://localhost:3000";

    if (!/^https?:\/\//.test(url)) {
        url = `http://${url}`;
    }

    // If we are running inside coolify we need to strip the port and append a schemema
    if (await isCoolify()) {
        const hostname = new URL(url).hostname;
        url = `https://${hostname}`;
    }

    return new URL(url);
}


Having the same issue in other places like sitemap.ts and manifest.webmanifest that base_url defaults to localhost.

I can confirm that COOLIFY_URL is set during runtime and buildtime (coolify passes it as build arg and in the container it's set)

2 Replies

@Transvaal lion Hey, I'm trying to dynamically use a base url in my project so they work when using preview deployments. For example this is my `robots.ts` file ts import type { MetadataRoute } from "next"; import { getBaseUrl } from "@actions/utils"; const baseUrl = await getBaseUrl(); const sitemapUrl = new URL("/sitemap.xml", baseUrl).toString(); export default function robots(): MetadataRoute.Robots { return { rules: { userAgent: "*", allow: ["/", "/llms.txt"], disallow: ["/dashboard", "/eventsub", "/proxy", "/overlay"], }, sitemap: sitemapUrl, }; } The generated robots.txt file looks like this: txt User-Agent: * Allow: / Allow: /llms.txt Disallow: /dashboard Disallow: /eventsub Disallow: /proxy Disallow: /overlay Sitemap: http://localhost:3000/sitemap.xml (should be myPreview-x6sa389xda.domain.com) This is my util.ts file: "use server"; export async function isPreview() { return String(process.env.IS_PREVIEW).toLowerCase() === "true"; } export async function isCoolify() { return Object.keys(process.env).some((key) => /^COOLIFY_/.test(key)); } export async function getBaseUrl(): Promise<URL> { let url = process.env.COOLIFY_URL || "http://localhost:3000"; if (!/^https?:\/\//.test(url)) { url = `http://${url}`; } // If we are running inside coolify we need to strip the port and append a schemema if (await isCoolify()) { const hostname = new URL(url).hostname; url = `https://${hostname}`; } return new URL(url); } Having the same issue in other places like sitemap.ts and manifest.webmanifest that base_url defaults to localhost. I can confirm that `COOLIFY_URL` is set during runtime and buildtime (coolify passes it as build arg and in the container it's set)
American Sable
@tsa you said you used coolify maybe you can help this guy
Chub mackerel
your robots/sitemap run at build time, so it falls back to localhost. add
export const dynamic = "force-dynamic";

to those files so COOLIFY_URL is read at runtime, or bake the preview URL into an env like NEXT_PUBLIC_SITE_URL.