How to access pathname
in generateMetadata
?
#50189
Replies: 22 comments 23 replies
-
If it's a dynamic URL param you can get it from the |
Beta Was this translation helpful? Give feedback.
-
Facing the same issue :( If anyone has an idea |
Beta Was this translation helpful? Give feedback.
-
I thought about just reading the name of the current file like so:
Have not tried it yet though ;) But I think this should be officially supported by NextJS |
Beta Was this translation helpful? Give feedback.
-
Looking around I found a way using headers api.
|
Beta Was this translation helpful? Give feedback.
-
Thank you @jmacbhc ! Furthermore, here's a snippet that turns nested routes to a nicely looking title: export async function generateMetadata({ params }: Props): Promise<Metadata> {
const headersList = headers();
const pathname = headersList.get("x-invoke-path") || "DefaultTitle";
const pathSegments = pathname.split("/").filter((segment) => segment !== ""); // Split pathname into segments and remove empty segments
const titleSegments = pathSegments.map(
(segment) => segment.charAt(0).toUpperCase() + segment.slice(1) // Capitalize the first letter of each segment
);
const title = titleSegments.join(" › "); // Join segments with a separator
return { title };
} // Example: "/home/profile" turns to "Home › Profile" Edit: This solution does not work in a Vercel deployment. |
Beta Was this translation helpful? Give feedback.
-
While the solution @jmacbhc proposed does work locally, it doesn't work when deploying the app on Vercel, so I opened #54711. Please continue the discussion over there. |
Beta Was this translation helpful? Give feedback.
-
Here is what I'm using for now:
import { NextResponse, type NextRequest } from "next/server";
export function middleware(request: NextRequest) {
request.headers.set("x-url", request.url);
return NextResponse.next();
}
import type { Metadata } from "next";
import { headers } from "next/headers";
export async function generateMetadata(): Promise<Metadata> {
const url = new URL(headers().get("x-url")!);
console.log(url.pathname);
return {};
} |
Beta Was this translation helpful? Give feedback.
-
Working in Next 14 middleware.ts
layout.ts
|
Beta Was this translation helpful? Give feedback.
-
The answers in this thread work but will make the route dynamically rendered instead of statically, because of calling headers(). As per Next.js Documentation on https://nextjs.org/docs/app/api-reference/functions/headers
I don't think this the best solution. |
Beta Was this translation helpful? Give feedback.
-
You also really need |
Beta Was this translation helpful? Give feedback.
-
This have to be joke about developer UX 😢 |
Beta Was this translation helpful? Give feedback.
-
After some consideration, I'm reopening this as the current solution is not giving access to |
Beta Was this translation helpful? Give feedback.
-
This is not your case, but I'd like to point out that: If you were trying to access the It looks like this: export const metadata = {
metadataBase: new URL('https://acme.com'),
alternates: {
canonical: '/',
languages: {
'en-US': '/en-US',
'de-DE': '/de-DE',
},
},
openGraph: {
images: '/og-image.png',
},
} |
Beta Was this translation helpful? Give feedback.
-
This should be part of the official documentation |
Beta Was this translation helpful? Give feedback.
-
+1, this is a significant issue with any website trying to manage titles properly. We need access to the URL and path name in |
Beta Was this translation helpful? Give feedback.
-
I need this too to set the right language alternatives. I am using
but for page
but I have no idea about the right way to access the pathname |
Beta Was this translation helpful? Give feedback.
-
I'm seeking a method to automatically populate the |
Beta Was this translation helpful? Give feedback.
-
After digging a little bit in generateMetadata params it seems there is an "unsafe" way to do that without opting out from cache. /**
* Get the pathname from the metadata state
* This dives into async storage of promise state to get the pathname
*
* This is much more performant that using headers() from next as this doesn't opt out from the cache
* @param state
*/
export const getPathnameFromMetadataState = (state: any): string | undefined => {
const res = Object.getOwnPropertySymbols(state || {})
.map(p => state[p])
.find(state => state?.hasOwnProperty?.("urlPathname"))
return res?.urlPathname.replace(/\?.+/, "")
} export async function generateMetadata(_: any, state: any): Promise<Metadata> {
const metaByPath = await fetchMetadataByPath()
const pathname = getPathnameFromMetadataState(state) ?? ""
const { title, description } = metaByPath[pathname] || {}
return {
title,
description,
}
} Pretty ugly, but it gets the job done 🤷♂️ |
Beta Was this translation helpful? Give feedback.
-
Adding another approach in case it helps someone. :-) If you are receiving params, and it happens to be a catchall segment, this might work for you: Folders:
Then you might be able to do this: export async function generateMetadata(params: {
params: { product: [...parts: string[]] };
}): Promise<Metadata> {
const {
params: {
product: [slug, id]
}
} = params;
// reconstitute URL from product, slug and id
const url = `${DOMAIN_FROM_SOMEWHRE}/products/${slug}/${id}`;
}```
|
Beta Was this translation helpful? Give feedback.
-
Is there a solution for this that doesn't involve making requests or getting headers? |
Beta Was this translation helpful? Give feedback.
-
According to this comment by @delbaoliveira , the reason why this is not possible currently is that Next.js restricts access to "request-time" data included in the Request object because it wants to have visibility over where this data is being accessed, and turn these access points to SSR instead of building them statically on build-time, and it does this by providing This goal is not affected by what we're trying to do here.What we need here is a way to identify the current route on build-time in |
Beta Was this translation helpful? Give feedback.
-
I'm looking for a way to dynamically generate
<title>
based on the currentpathname
.For example,
/store
would becometitle: 'Store'
ingenerateMetadata()
.This would also allow for a nested
pathname
to turn into a nestedtitle
, for example/store/hoodies/dark-hoodie
could turn intotitle: 'Store - Hoodies - Dark Hoodie'
.Is there a way to do this currently in Next 13?
Beta Was this translation helpful? Give feedback.
All reactions