---
title: "Discussion on \"Open Graph Tags in a React + Vite SPA: Why Crawlers See Your App Shell, and Three Ways to Fix It\" | Hashnode"
description: "Discussion on \"Open Graph Tags in a React + Vite SPA: Why Crawlers See Your App Shell, and Three Ways to Fix It\". If you've built a single-page app with React and Vite, you've probably seen this: every link you share, whether it's /pricing, /blog/my-post or /u/someone, shows the same card. Usually it's the title"
url: "https://hashnode.com/posts/open-graph-tags-in-a-react-vite-spa-why-crawlers-see-your-app-shell-and-three-ways-to-fix-it/6ad1d8df805838e2d93d7ce3"
---

[Feed](https://hashnode.com/feed) /

Discussion

# [Open Graph Tags in a React + Vite SPA: Why Crawlers See Your App Shell, and Three Ways to Fix It](https://abidali671.hashnode.dev/open-graph-tags-in-a-react-vite-spa-why-crawlers-see-your-app-shell-and-three-ways-to-fix-it?utm_source=hashnode&utm_medium=feed)

If you've built a single-page app with React and Vite, you've probably seen this: every link you share, whether it's /pricing, /blog/my-post or /u/someone, shows the same card. Usually it's the title

Oct 16 · 6 min read · abidali671.hashnode.dev  
Read the article

-   [#react](https://hashnode.com/tag/react)
-   [#vite](https://hashnode.com/tag/vite)
-   [#seo](https://hashnode.com/tag/seo)
-   [#opengraph](https://hashnode.com/tag/opengraph)
-   [#javascript](https://hashnode.com/tag/javascript)

## Written by

[Abid Ali](https://hashnode.com/@abidali671)

@abidali671 · Karachi, Pakistan

  
[View profile](https://hashnode.com/@abidali671)

Full Stack Developer | Next.js, React, TypeScript | Building OG Scope, Digital Dialogue & Meme Tap

I'm Abid Ali, a full stack developer from Karachi with 3+ years of experience in TypeScript, Next.js, Gatsby, React and React Native. I build web apps, mobile apps and interactive UIs with solid API integration. Side projects: OG Scope (ogscope.pk), a free Open Graph checker; Digital Dialogue (digitaldialogue.pk), freelancing guides for Upwork and Fiverr beginners; and Meme Tap (memetap.pk), a free browser meme soundboard.

## Responses 3

Markdown supported · ⌘↵ to post

[Tarun Sharma](https://hashnode.com/@101beardo)

[Oct 17](https://hashnode.com/posts/open-graph-tags-in-a-react-vite-spa-why-crawlers-see-your-app-shell-and-three-ways-to-fix-it/6ad1d8df805838e2d93d7ce3/comment/6ad2f96bfc7e53d3b307ce8a)

Option 3 swapping values into the default tags is a neat way to avoid user-agent sniffing. One edge case I wondered about: when the API returns a 404 for a deleted post, the function falls back to the shell with generic tags, so crawlers get a 200 and a default card for a page that no longer exists. Do you return a real 404 status from the edge in that case, or is the generic card fine for you?

[Abid Ali](https://hashnode.com/@abidali671)

[Oct 17](https://hashnode.com/posts/open-graph-tags-in-a-react-vite-spa-why-crawlers-see-your-app-shell-and-three-ways-to-fix-it/6ad1d8df805838e2d93d7ce3/comment/6ad2f96bfc7e53d3b307ce8a#reply-6ad34cc9c002f7921aee1241)

Good catch, Tarun, and you're right. As written, a 404 from the API falls through to `return res`, so crawlers get a 200 and the default card for a post that's gone. That's a soft 404, and it isn't great for search engines or for previews.

I'd split it by the API's status:

```js
const apiRes = await fetch(`api.acme.com/posts/$%7Bmatch[1]}`);
if (apiRes.status === 404) {
  return new Response(res.body, { status: 404, headers: res.headers });
}
if (!apiRes.ok) return res; // 5xx or timeout: fall back to the shell
const post = await apiRes.json();
```

Users still get the SPA's own "not found" view, since it's the same shell, but crawlers now see a real 404, and most platforms won't build a card from it. For 5xx errors and timeouts I'd keep the generic card, so a temporary API problem doesn't wipe out previews. Adding `<meta name="robots" content="noindex">` on the 404 path is a nice extra. Thanks for reading closely!

[StackShortlist](https://hashnode.com/@veristria)

[Oct 16](https://hashnode.com/posts/open-graph-tags-in-a-react-vite-spa-why-crawlers-see-your-app-shell-and-three-ways-to-fix-it/6ad1d8df805838e2d93d7ce3/comment/6ad2ab1cff3a3473c2720d31)

The edge function approach is a nice middle ground, since it only rewrites the head for crawler user agents and leaves the SPA untouched for everyone else. One gotcha is caching: Slack, LinkedIn and Facebook all cache the card aggressively, so testing with their debug tools and forcing a rescrape saves a lot of confusion. Setting og:image dimensions explicitly also helps some platforms render the large card on the first share.
