Next.js Discord

Discord Forum

Stale Metadata in Dynamic Routes When Adding to Home Screen on Mobile devices. help :(

Unanswered
alle ⸺⸙ posted this in #help-forum
Open in Discord
Hi, I've encountered a metadata issue with dynamic routes that I haven't been able to solve. The problem occurs when adding pages to the home screen on Android devices. Here's what happens:

1. When I first visit a page (e.g., /cats/maine-coon or /cats) and try to add it to the home screen, the "Create Shortcut" dialog shows the correct title and shortcut icon.
2. However, if I navigate to a different cat's page (e.g., /cats/persian) and try to add it to the home screen, the dialog shows the metadata (title and icon) from the previous page, not the current cat.
3. To get the correct metadata to show up, I need to manually reload the page 1-2 times, depending on the browser.

As far as I know, this issue only occurs on mobile devices (Android tested with Chrome, Firefox, and Edge)

This is my metadata configuration for the dynamic route:
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params;
  const response = await findOneCat(slug);
  if (response.status === "error") { return { title: "Cat not found" }; }
  const cat = response.data;
  return {
    title: cat.name,
    description: cat.description,
    icons: {
      ...METADATA_ICONS,
      apple: {
        url: cat.appleIcon,
        sizes: "180x180",
      },
      shortcut: {
        url: cat.shortcutIcon,
        sizes: "96x96",
      },
    },
    openGraph: {
      title: cat.name,
      description: cat.description,
      images: cat.image,
      type: "website",
      siteName: `${SITE_NAME} ${COUNTRY_CODE_NAME[COUNTRY_CODE]}`,
      url: `/cats/${cat.slug}`,
    },
    twitter: {
      card: "summary_large_image",
      title: cat.name,
      description: cat.description,
      images: cat.image,
    },
  };
}

This issue can be reproduced on my deployed site: https://cats-metadata-ten.vercel.app/cats/maine-coon
Does anyone knows how can i fix this?

18 Replies

bump
bump
bump
bump
bump
bump
bump
bump
bump
bump
bump
@alle ⸺⸙ Hi, I've encountered a metadata issue with dynamic routes that I haven't been able to solve. The problem occurs when adding pages to the home screen on Android devices. Here's what happens: 1. When I first visit a page (e.g., `/cats/maine-coon` or `/cats`) and try to add it to the home screen, the "Create Shortcut" dialog shows the correct title and shortcut icon. 2. However, if I navigate to a different cat's page (e.g., `/cats/persian`) and try to add it to the home screen, the dialog shows the metadata (title and icon) from the previous page, not the current cat. 3. To get the correct metadata to show up, I need to manually reload the page 1-2 times, depending on the browser. As far as I know, this issue only occurs on mobile devices (Android tested with Chrome, Firefox, and Edge) This is my metadata configuration for the dynamic route: typescript export async function generateMetadata({ params }: Props): Promise<Metadata> { const { slug } = await params; const response = await findOneCat(slug); if (response.status === "error") { return { title: "Cat not found" }; } const cat = response.data; return { title: cat.name, description: cat.description, icons: { ...METADATA_ICONS, apple: { url: cat.appleIcon, sizes: "180x180", }, shortcut: { url: cat.shortcutIcon, sizes: "96x96", }, }, openGraph: { title: cat.name, description: cat.description, images: cat.image, type: "website", siteName: `${SITE_NAME} ${COUNTRY_CODE_NAME[COUNTRY_CODE]}`, url: `/cats/${cat.slug}`, }, twitter: { card: "summary_large_image", title: cat.name, description: cat.description, images: cat.image, }, }; } This issue can be reproduced on my deployed site: https://cats-metadata-ten.vercel.app/cats/maine-coon Does anyone knows how can i fix this?
force dynamic on the route so that the server sends the new document on navigation
also, are u using the link component from next
@gin also, are u using the link component from next
Hey, thank you very much for responding, yes I am using the Next Link component in all my redirects, for example this is the code I have in the listing page, in /cats
      <section className="grid grid-cols-1 place-items-center md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
        {CATS.map((cat) => (
          <Link
            prefetch
            key={cat.slug}
            className="rounded-xl border-[2px] border-white/25 p-4 grid grid-cols-[144px_1fr] gap-x-4 max-w-96 w-full overflow-x-scroll lg:overflow-x-hidden min-h-[180px] max-h-[180px] hover:border-white/70 transition-colors"
            href={`/cats/${cat.slug}`}
          >
            <Image
              className="object-cover aspect-square size-36 rounded-lg"
              src={cat.image}
              alt={cat.name}
              width={144}
              height={144}
            />
            <div className="flex flex-col gap-1">
              <h3 className="text-xl font-semibold">{cat.name}</h3>
              <p className="line-clamp-4 text-[#ededed]/70">
                {cat.description}
              </p>
            </div>
          </Link>
        ))}
      </section>


although I hadn't tried forcing dynamic before, I'm going to try to do it
alr
I just tried it, and deployed again on Vercel but there was no change, this would be the way to add it, right?
// app/cats/[slug]/page.tsx

type Props = {
  params: Promise<{
    slug: string;
  }>;
};

export const dynamic = "force-dynamic";

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params;

  const response = await findOneCat(slug);

  if (response.status === "error") {
    return { title: "Cat not found" };
  }

  const cat = response.data;

  return {
    // rest of the code
  };
}

export default async function CatPage({ params }: Props) {
  const { slug } = await params;

  const response = await findOneCat(slug);

  if (response.status === "error") {
    return notFound();
  }

  const cat = response.data;

  return <div>{/* rest of the code */}</div>;
}
bump
bump