<PreviousNext>

Developer Update: Next.js App Router SEO Fixes That Improved Indexing and Crawlability

Hello everyone! It’s the developer of the project. Over the last few days I went deep into a problem that was bothering me: Google was indexing my site slower and less consistently than expected.

After a thorough audit, I found multiple technical causes — and I’ve now fixed the major ones. The biggest lesson for me is simple: the site didn’t need “SEO tricks,” it needed correct rendering, clean structure, and clear intent. I still have a lot to learn, but the foundation is now much stronger.

1) The biggest issue: Client Boundary placement (the “client tree” problem)

What was wrong: I wrapped too much of the page inside ReduxProvider directly within a server component (for example, inside CharacterPage).

Why it hurts indexing: In Next.js App Router, placing a client provider too high in the tree can cause large parts of the page to become client-rendered. In that scenario, crawlers may see an incomplete HTML response (or mostly skeleton markup) because the meaningful content is expected to render in the browser.

How it was fixed: I moved client-only logic down the tree and wrapped only the components that truly require it (for example, Chat and DownloadButton). All primary content — headings (H1), descriptive text, and FAQ — remains pure server-rendered HTML.

2) Heading hierarchy issues (duplicate H1)

What was wrong: My JSON description already contained an <h1>, and the page layout added another <h1> above it.

Why it’s a problem: Multiple H1 tags can blur the main topic signal. It makes page structure less clear for both crawlers and users.

How it was fixed: I implemented normalizeDescriptionHeadings to convert nested h1 into h2, ensuring one clear primary H1 per page.

3) Keyword clarity in the primary heading (H1)

What was wrong: I wanted an artistic H1 like “A Night of Devotion in the Abyss” instead of a heading that matches what people actually search for.

Why it matters: Search engines rank pages that clearly match user intent. If the H1 doesn’t contain the core query term (for example: character name + page type), the page is harder to understand and less discoverable.

How it was fixed: H1 now uses clear intent (for example: character name + suffix like Fanart, Gallery, Wallpapers). Any creative/atmospheric line is placed in H2, so it keeps style without weakening discoverability.

4) Meta description generation (“dirty cut” problem)

What was wrong: I used .slice(0, 160) to generate meta descriptions.

Why it’s bad: Cutting text mid-sentence or mid-word can look unpolished in search results and may reduce click-through rate.

How it was fixed: I replaced it with truncateByWords so descriptions end cleanly on word boundaries.

5) Cannibalization from near-identical pages

What was wrong: I generated many pages for the same character without strong differentiation in Title/H1 (weak or inconsistent suffix intent).

Why it hurts: When multiple pages target the same meaning, Google may select one as the primary result and ignore the rest — reducing overall coverage.

How it was fixed: I expanded and standardized suffix intent (for example: Wallpapers, 4K, Gallery) so each page targets a distinct micro-query and provides a unique purpose.

6) Missing structured data (JSON-LD)

What was wrong: I relied mainly on visible page text and didn’t provide structured data.

Why it matters: Without JSON-LD, search engines have fewer explicit signals about the page structure, and the page may miss eligibility for enhanced result formats.

How it was fixed: I added JSON-LD where appropriate (including FAQPage and content-related schema like ImageGallery/VideoObject when relevant).

7) Misleading keywords that don’t match page intent

What was wrong: Some suffixes implied content types that the page did not actually provide (for example: “Wiki”, “Lore”, “Walkthroughs”).

Why it hurts: This can misalign expectations. When users land on a page that doesn’t match what they were looking for, they tend to leave quickly — which can reduce perceived relevance and overall performance.

How it was fixed: I filtered suffixes to match the real page intent (visual/gallery intent) and removed misleading terms.

Final thoughts

The most impactful issue was the client provider placement — it could turn a page with strong on-page SEO into something crawlers don’t reliably receive as HTML. Now that ReduxProvider is used only where necessary, SSR/SSG can do its job properly again.

Thanks for reading and for supporting the project. I’ll keep improving performance, indexing consistency, and overall quality step by step.

FAQ

  • What is this page about?
    After several intense days investigating slow Google indexing, I identified a set of technical SEO issues in my Next.js App Router pages. I’ve now shipped targeted fixes that keep critical content server-rendered, improve page structure, and make the site more consistently crawlable and search-friendly.
  • How many words is this article?
    About 753 words.
  • How long does it take to read?
    Approximately 4 minutes at a normal pace.
  • Permalink
    /en/news/developer-update-nextjs-app-router-seo-fixes

Meet Our Characters

Cecilia Aquarain - There Was A Cute Girl In The Hero’s Party (yuukawa)
Cecilia Aquarain - There Was A Cute Girl In The Hero’s Party (yuukawa)
Open
Cecilia Aquarain - There Was A Cute Girl In The Hero’s Party (yuukawa)
Open
Yuuki Sorimachi - Shiboyugi: Playing Death Games To Put Food On The Table (shibou Yuugi De Meshi O Kuu)
Yuuki Sorimachi - Shiboyugi: Playing Death Games To Put Food On The Table (shibou Yuugi De Meshi O Kuu)
Open
Yuuki Sorimachi - Shiboyugi: Playing Death Games To Put Food On The Table (shibou Yuugi De Meshi O Kuu)
Open
Selma Claudel - Banished From The Hero's Party (yuusha Party Wo Oidasareta Kiyoubinbou)
Selma Claudel - Banished From The Hero's Party (yuusha Party Wo Oidasareta Kiyoubinbou)
Open
Selma Claudel - Banished From The Hero's Party (yuusha Party Wo Oidasareta Kiyoubinbou)
Open
Sagiri Yamada Asaemon - Hell's Paradise - Jigokuraku
Sagiri Yamada Asaemon - Hell's Paradise - Jigokuraku
Open
Sagiri Yamada Asaemon - Hell's Paradise - Jigokuraku
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open
Ruti Ragnason - Banished From The Hero’s Party (shin No Nakama)
Ruti Ragnason - Banished From The Hero’s Party (shin No Nakama)
Open
Ruti Ragnason - Banished From The Hero’s Party (shin No Nakama)
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open
Shizuku Yaegashi - Arifureta: From Commonplace To World's Strongest (shokugyou De Sekai Saikyou)
Open