·3 min read·Mounaji Studio

Keep shared links on the right domain: canonical, og:url and the trailing slash

One variable with an extra slash or a leftover Vercel host, and every shared link goes out on the wrong domain. The six-line function that normalizes it in vendear, where it is used, and why it points to www and not the bare domain.

engineeringseowebvendear

Also in: Español

On vendear, every business has its own storefront with its own link, and that link is what the owner shares on WhatsApp and Instagram. Nobody types the domain in that link by hand: it comes from an environment variable, and from there it flows into the canonical, the og:url, the sitemap and the copy button in the owner's panel.

If that variable is wrong, all of them break at once. There are two common ways for it to be wrong:

  • A trailing slash. https://www.vendear.com/ plus /es/<business> builds https://www.vendear.com//es/<business>. It works in the browser, but it is a different URL for search engines and looks broken in a chat.
  • The Vercel host. If the variable was set before the site had its own domain, it still says https://<project>.vercel.app, and every shared link carries that host.

We had both at the same time: links went out as https://<project>.vercel.app//es/<business>.

The function

Everything goes through one place, src/config/brand.js:

export const DEFAULT_SITE_URL = "https://www.vendear.com";

export function normalizeSiteUrl(raw, vercelEnv) {
  const value = String(raw || "").trim().replace(/\/+$/, "");
  if (!value) return DEFAULT_SITE_URL;
  // A *.vercel.app in production is stale config, not a choice: the site
  // has its own domain. In previews and locally it is fine.
  if (vercelEnv === "production" && /\.vercel\.app$/i.test(value)) return DEFAULT_SITE_URL;
  return value;
}

export const BRAND = {
  baseUrl: normalizeSiteUrl(
    process.env.NEXT_PUBLIC_SITE_URL,
    process.env.NEXT_PUBLIC_VERCEL_ENV || process.env.VERCEL_ENV
  ),
  // …
};

Three values of the variable and what comes out in production: a trailing slash is trimmed; a .vercel.app host and an empty variable fall back to https://www.vendear.com. One output feeds canonical, og:url, sitemap and the link the owner copies

There are three decisions in those six lines.

1. Trim the slash instead of trusting whoever sets it

replace(/\/+$/, "") strips every trailing slash. Asking whoever configures the project not to add one does not work: variables get copied and pasted, and a trailing slash is invisible in a form. Normalizing it every time is cheaper.

2. A Vercel host is a mistake in production, not in a preview

In production, a *.vercel.app is not a choice: the site has its own domain and that value is left over. So it is ignored and the default domain is used. In a preview, though, the Vercel host is exactly what you want: links should lead to the preview, not to production. The function looks at the environment to decide.

One detail: NEXT_PUBLIC_VERCEL_ENV is read before VERCEL_ENV because the panel also imports this file, and it runs in the browser, where only variables with the public prefix exist.

3. www, not the bare domain

vendear.com answers with a 308 redirect to www.vendear.com. You can check it:

curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://vendear.com/es/almacendemo
# 308 https://www.vendear.com/es/almacendemo

If the canonical and the og:url pointed to the bare domain, every crawler (the search engines' and the one that builds the preview in WhatsApp or Facebook) would have to follow that redirect to reach the page. Some do, but one hop fewer is one failure point fewer. The default is the URL that answers 200 directly.

One place for everything

The real win is not the function but that everything uses it. In vendear, BRAND.baseUrl feeds:

  • the layout's metadataBase, from which Next.js builds the canonical and og:url;
  • the preview image URL (/api/og/<business>);
  • sitemap.xml, robots.txt and llms.txt;
  • the home page's structured data (JSON-LD);
  • the link the owner copies from their panel.

Before, the panel built its own link. Now there are no two paths that can disagree.

How to check it

Look at what a crawler reads, not at what the browser shows:

curl -s https://www.vendear.com/es/almacendemo \
  | grep -o '<link rel="canonical"[^>]*>\|<meta property="og:url"[^>]*>'
<link rel="canonical" href="https://www.vendear.com/es/almacendemo"/>
<meta property="og:url" content="https://www.vendear.com/es/almacendemo"/>

No double slash and no Vercel host. Measured on October 5, 2026.

If your site builds absolute URLs from a variable, those two lines are worth a look. And to see how a shared link arrives, open www.vendear.com/es/almacendemo and share it in a chat.

Comments and corrections

Chat with us