Introduction: A site that works perfectly, but no OGP?
One of the most terrifying bugs in web development is a bug where "the site works perfectly in the browser, but there's a fatal problem occurring behind the scenes."
This time, I'll share a story about a "mistake in implementing a loading screen that nearly wiped out SEO" which I actually encountered in a Next.js project.
If you're struggling with symptoms like "OGP not being reflected after building a site with Next.js" or "favicons not appearing in Google search results," this article should provide a clue to the solution.
The Incident: "Not Recognized" Even with Status Code 200
The site construction was completed, and it was deployed to the production environment. I checked its operation in the browser. The animations were smooth, page transitions were lightning fast. I thought it was "perfect."
However, the moment I tried to share it on social media, I noticed something unusual.
- OGP images were not displayed even when posting URLs on Twitter (X) or Facebook.
- Favicons and descriptions were not reflected in Google search results, no matter how long I waited.
When I hit the URL with Facebook's debugger tool, the HTTP status code returned 200 OK. The server was alive. But the title and image information showed "could not be retrieved."
Debugging Gone Astray: Days of Suspecting Authentication and Caching
Initially, I suspected the Next.js and Vercel settings.
- "Is Vercel's Authentication (e.g., Basic Auth) accidentally ON?" → Checked, it was OFF.
- "Is the CSP (Content Security Policy) header too strict and blocking crawlers?" → Tried disabling it, but no change.
- "Is it just bot cache remaining?" → Accessed with different URL parameters, but the situation didn't change.
Even after reviewing the configuration files, I couldn't find any suspicious areas. I was completely lost in a maze.
Decisive Evidence: The "Void" Seen by the curl Command
"Why can't crawlers see what's visible in the browser?"
Returning to basics, I decided to look at the site from a "bot's perspective." What helped here was not the browser's inspection tool, but the curl command executed in the terminal.
I tried accessing it using the following command, impersonating Facebook's crawler (facebookexternalhit).
I was astonished when I saw the returned HTML.
The content was completely empty. There was no title or OGP tag within the <head>, and only the text "Loading..." in the body. With this, there was no way a crawler could understand the site's content.
A Trap Not Noticed with Browser Developer Tools Alone
Normally, we tend to check HTML using "Developer Tools" (DevTools) in browsers like Chrome. However, modern browsers are smart and display the DOM "after" JavaScript has been executed.
In contrast, many crawlers (especially OGP fetching bots) make judgments based on the initial HTML returned from the server (initial response). There was a critical discrepancy here.
The Real Culprit: Conditional Rendering during SSR
The cause was in how conditional rendering was written in _app.tsx, which is the root of the application.
When checking authentication status, I had implemented it to "only show a loading screen during the check" in an attempt to improve the user experience.
❌ The Culprit Code
Why is this bad?
- Hooks such as
useAuthanduseEffectare executed only on the client-side (browser). - At the time of Next.js's SSR (Server-Side Rendering),
isCheckingproceeds with its initial value (e.g.,true). - The server follows
if (true)and generates an HTML response containing only<Preloader />. - The crawler receives this "Preloader-only HTML" and returns, judging it to be an "empty page."
In a browser, which humans see, the content switches after JavaScript runs, so we don't notice, but for bots, it was a "permanently loading page."
Solution: "Overlay" Instead of "Switching"
The solution was simple. It was to "always render the content (Component) regardless of whether it's loading." After that, I changed the implementation to overlay the loading screen using CSS.
⭕️ Correct Code
CSS Control (Preloader)
The Preloader component is styled to cover the entire screen with properties like position: fixed; z-index: 9999;. This maintains the visual behavior (content is not visible during loading) while creating a state where the content exists in the HTML structure.
Immediately after deploying this fix, checking with the curl command confirmed that <title> and <meta property="og:image"> were properly output, and social media display was successfully restored.
Summary: Treating SSR with a React Mindset Can Kill Your SEO
When accustomed to developing only SPAs (Single Page Applications) or with just React, it's common to "separate returns based on conditions." However, with frameworks that involve SSR like Next.js, you must always be conscious of "what is included in the initial HTML returned by the server."
Lessons learned this time:
- Be wary of conditional rendering: Check that content is not excluded during SSR.
- The curl command is your friend: For SEO-related troubleshooting, get in the habit of checking the raw HTML with
curlinstead of the browser.
If you're wondering "why isn't OGP appearing?", try accessing your site from the terminal once. You might discover an unexpected "void."

![[Next.js] Was the cause of OGP not appearing a 'loading screen'? Implementation Mistakes that Kill SEO and Their Solutions のビジュアル](/_next/image?url=https%3A%2F%2Fimages.microcms-assets.io%2Fassets%2Fd715df12cb1c437abed660489fde6d5a%2F550c24735663434082b90093a9b2f834%2Fnextjs-seo-loading-issue.png&w=1920&q=75&dpl=dpl_FYqBhuikYDMuNGE5MP5RYSgt6tk5)