You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When metaBaseUrl is unset, prefer nuxt-site-config site.url
over the request origin so SEO stacks need one source of truth.
Closes#240
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: docs/api/module-options.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -91,7 +91,7 @@ Meta tags generated for each localized page.
91
91
| Option | Type | Default | Description |
92
92
| --- | --- | --- | --- |
93
93
|`meta`|`boolean`|`true`| Generate SEO meta tags (`hreflang`, `canonical`, `og:url`, `og:locale`) automatically. |
94
-
|`metaBaseUrl`|`string`|`undefined`| Base URL for SEO meta tags (canonical, og:url, hreflang). - `undefined` — dynamically resolved from the current request URL (`useRequestURL().origin` on server, `window.location.origin` on client). Best for multi-domain deployments. - A concrete URL string (e.g. `'https://example.com'`) — used as-is. |
94
+
|`metaBaseUrl`|`string`|`undefined`| Base URL for SEO meta tags (canonical, og:url, hreflang). - A concrete URL string (e.g. `'https://example.com'`) — used as-is (highest priority). - `undefined` — falls back to `site.url`from `nuxt-site-config` when that module is present, otherwise the current request origin (`useRequestURL().origin` on server, `window.location.origin` on client). |
95
95
|`metaTrustForwardedHost`|`boolean`|`true`| Trust the `X-Forwarded-Host` header when resolving the base URL for meta tags. Enable when the app runs behind a reverse proxy (nginx, Cloudflare, AWS ALB, etc.) that sets this header to the real client-facing hostname. |
96
96
|`metaTrustForwardedProto`|`boolean`|`true`| Trust the `X-Forwarded-Proto` header when resolving the protocol for meta tags. Enable when the app runs behind a TLS-terminating proxy so that canonical URLs use `https://` even though the app itself listens on HTTP. |
97
97
|`canonicalQueryWhitelist`|`string[]`|`['page', 'sort', 'filter', 'search', 'q', 'query', 'tag']`| List of query parameter names preserved in canonical and `og:url` meta tags. Parameters not in this list are stripped from the canonical URL. |
Copy file name to clipboardExpand all lines: docs/guide/configuration.md
+13-10Lines changed: 13 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ The sections below explain how they work together; the
21
21
|[`locales`](/api/module-options)|`Locale[]`|`[]`| List of supported locales. |
22
22
|[`meta`](/api/module-options)|`boolean`|`true`| Generate SEO meta tags (`hreflang`, `canonical`, `og:url`, `og:locale`) automatically. |
23
23
|[`strategy`](/api/module-options)|`Strategies`|`'prefix_except_default'`| URL routing strategy for locale prefixes. - `'no_prefix'` — no locale in URL; locale stored in cookie. - `'prefix_except_default'` — prefix all locales except the default. - `'prefix'` — always prefix, including the default locale. - `'prefix_and_default'` — like `prefix`, but the default locale is also accessible without prefix. |
24
-
|[`metaBaseUrl`](/api/module-options)|`string`|`undefined`| Base URL for SEO meta tags (canonical, og:url, hreflang). - `undefined` — dynamically resolved from the current request URL (`useRequestURL().origin` on server, `window.location.origin` on client). |
24
+
|[`metaBaseUrl`](/api/module-options)|`string`|`undefined`| Base URL for SEO meta tags (canonical, og:url, hreflang). - A concrete URL string (e.g. `'https://example.com'`) — used as-is (highest priority). - `undefined` — falls back to `site.url`from `nuxt-site-config` when that module is present, otherwise the current request origin (`useRequestURL().origin` on server, `window.location.origin` on client). |
25
25
|[`metaTrustForwardedHost`](/api/module-options)|`boolean`|`true`| Trust the `X-Forwarded-Host` header when resolving the base URL for meta tags. |
26
26
|[`metaTrustForwardedProto`](/api/module-options)|`boolean`|`true`| Trust the `X-Forwarded-Proto` header when resolving the protocol for meta tags. |
27
27
|[`hreflangBaseLanguage`](/api/module-options)|`boolean`|`false`| Also emit a bare-language `hreflang` derived from each locale's `iso` (e.g. `es-ES` → also `es`). |
Base URL for SEO meta tags (canonical, og:url, hreflang).
368
368
369
-
-`undefined` — dynamically resolved from the current request URL
369
+
- A concrete URL string (e.g. `'https://example.com'`) — used as-is (highest priority).
370
+
-`undefined` — falls back to `site.url` from `nuxt-site-config` when that module is
371
+
present, otherwise the current request origin
370
372
(`useRequestURL().origin` on server, `window.location.origin` on client).
371
-
Best for multi-domain deployments.
372
-
373
-
- A concrete URL string (e.g. `'https://example.com'`) — used as-is.
374
373
375
374
<!-- /generated:option:metaBaseUrl -->
376
375
377
-
-`undefined` (or omitted) — the base URL is resolved dynamically from the incoming request on the server (`useRequestURL().origin`, respects `X-Forwarded-Host` / `X-Forwarded-Proto` proxy headers) and from `window.location.origin` on the client. Ideal for **multi-domain** deployments where the same application serves multiple hostnames.
378
-
- Any other string — used as a static base URL.
376
+
Priority when unset: `site.url` from `nuxt-site-config` (if installed) → request origin
377
+
(`useRequestURL().origin` on the server with `X-Forwarded-Host` / `X-Forwarded-Proto`,
378
+
`window.location.origin` on the client). Ideal for **SEO stacks** that already set `site.url`,
379
+
and for **multi-domain** deployments when `site.url` is omitted.
380
+
381
+
- Any other string — used as a static base URL (wins over `site.url`).
379
382
380
383
```typescript
381
-
//Dynamic — automatically uses the current request hostname (recommended for multi-domain)
382
-
// Simply omit metaBaseUrl or set it to undefined
384
+
//Prefer sharing the SEO stack origin — omit metaBaseUrl when site.url is set
### 🌍 Dynamic `metaBaseUrl` for Multi-Domain Deployments
102
102
103
-
By default (`metaBaseUrl` is `undefined`), canonical URLs, `og:url`, and `hreflang` links are generated using the hostname from the current request. This is resolved via `useRequestURL()` on the server and `window.location.origin` on the client.
103
+
When `metaBaseUrl` is unset, absolute SEO URLs resolve in this order (#240):
104
104
105
-
The module respects reverse-proxy headers (`X-Forwarded-Host`, `X-Forwarded-Proto`), so it works correctly behind nginx, Cloudflare, AWS ALB, and similar proxies.
105
+
1.`site.url` from [`nuxt-site-config`](https://nuxtseo.com/docs/site-config) (if that module is present — e.g. via `@nuxtjs/seo`)
106
+
2. Otherwise the hostname from the current request (`useRequestURL()` / `window.location.origin`)
106
107
107
-
This means a single application instance can serve **multiple domains** with correct SEO tags for each:
108
+
The request-origin fallback respects reverse-proxy headers (`X-Forwarded-Host`, `X-Forwarded-Proto`), so it works correctly behind nginx, Cloudflare, AWS ALB, and similar proxies.
109
+
110
+
That means apps already setting `site.url` for sitemap / robots / schema.org do **not** need a second `metaBaseUrl` declaration:
111
+
112
+
```typescript
113
+
exportdefaultdefineNuxtConfig({
114
+
site: {
115
+
url: process.env.NUXT_SITE_URL, // also used by micro for canonical / og:url / hreflang
116
+
},
117
+
i18n: {
118
+
meta: true,
119
+
// metaBaseUrl omitted — picks up site.url, then request origin
120
+
},
121
+
})
122
+
```
123
+
124
+
Without `site.url`, a single application instance can still serve **multiple domains** with correct SEO tags for each via the request origin:
108
125
109
126
```typescript
110
127
exportdefaultdefineNuxtConfig({
@@ -127,7 +144,7 @@ While the same app serving `https://site-b.com/en/about` will produce:
0 commit comments