← Blog

Don't Let Google Miss Your Posts — SEO Pitfalls of an SSR Blog

· 5 min read · 8 views
Astro SEO SSR Sitemap JSON-LD
SSR Blog Practical Challenge

Don't let Google not find your article

The SSR Blog's SEO Troubleshooting Fact Sheet

During the process of building a blog with Astro + PostgreSQL, the reasons behind every SEO decision—and the pitfalls that almost made

Question

Why is SEO for SSR Blog different from static sites?#

1

Dynamic Content is not available on Sitemap#

The SSR page is generated by runtime.@astrojs/sitemap Only the build-time static page is included.

Article posted but not in sitemap = Google doesn't even know it exists.

2

Tool Schema is not the only stealth formatter.#

Like MCP tokens, SEO also has "hidden costs": missing meta tags, hreflang errors, canonical inconsistencies.

67% Multi-language station hreflang implementation error.

3

SSR's Double Edge of Performance#

SSR allows content to be updated in real time, but also makes TTFB subject to DB query times.

No caching strategy = run DB query on every request.

technology pallet

Composition of this Blog#

Astro 5
organizing plan
PostgreSQL
Databases
Drizzle
ORM Enquiry Layer
Tailwind
style
Cloudflare
Tunnel Deployment
SEO Solutions

What have we done?#

Each layer deals with an SEO orientation, with clear consumers from top to bottom.

Dynamic Sitemap
sitemap-posts.xml Query published articles from DB, automatically patch them in when building.sitemap-index.xml
🔍 Google / Bing crawlers
JSON-LD Structured Data
Auto-generate BlogPosting schema for each post - title, author, publish time, language all mapped from DB fields.
📊 Search Result Enrichment Summary
Canonical URL
SSR pages automatically set canonical to point to themselves. Avoidhttp://localhost cap (a poem)https://blog.joneshong.com Convicted of duplication
🔗 De-duplication mechanism
hreflang Multilingual
zh-TW ↔ en Bidirectional alternate link, plus x-default fallback. 67% of sites do this incorrectly!
🌐 Multilingual Search
robots.txt
Allow crawlers to access all public pages, blocking/admin/ cap (a poem)/api/The Points to two sitemap
🤖 reptile control
efficacy

Core Web Vitals Optimization#

0 KB
JS baseline
Astro Default Zero JS
according demand
React island hydration
Searching, mapping
delay
Font Loading Strategy
CJK system fonts + Latin lazy load
SSR
Dynamic Content
Live Updates

Astro's ultimate weapon:By default, no JavaScript is sent. React components only hydrate where they need to interact (client:onlyThe rest is static HTML.

Treadmill Records

How did we find out?#

It's not about pre-designing the SEO and then implementing it - it's about stepping into each hole and realizing it.

Article posted → Google can not search

sitemap-posts.xml No one's quoting.#

@astrojs/sitemap generatingsitemap-index.xml This page contains only static pages. Dynamicsitemap-posts.xml Ignored. Fixed: automatically patch sitemap-index to add posts sitemap after build.

Leadership:The automation tool may not cover all cases, and the SSR dynamics page needs to be filled manually.

A 12-minute post shows 73 min read

Rich HTMLcontent.length Includes the entire CSS#

content.length / 400 Counts the reading time, but Rich HTML formatted content has 25000+ words of CSS + HTML tags. strip tags are correct.

Leadership:Any logic related to the length of the content should be preceded by "what format is this content in".

Nginx subpath proxy The next page is blank.

Vite dev server + subpath = dead path#

Vite's ES module import uses absolute path, nginxsub_filter I can't finish it. Solution: dev preview doesn't use Vite dev server, use built SSR server instead.

Leadership:Astro islandscomponent-url Attributes need to be rewritten by sub_filter as well.

Take this away.

Copy to your AI Agent#

Paste the following paragraph to your AI coding agent so that it can help you evaluate the SEO settings of your SSR Blog.

Help me evaluate if there are any omissions in the SEO settings of this SSR Blog. Currently implemented: - Dynamic sitemap (DB query for published articles, patched into sitemap-index during build) - JSON-LD BlogPosting schema (automatically generated from article fields) - Canonical URL (each page automatically points to itself) - hreflang (zh-TW ↔ en bidirectional alternate) - robots.txt (allows public pages, blocks admin/api) - Astro zero JS baseline + React islands on-demand hydration Please help me check: - Are there any missing meta tags (e.g., og:image, twitter:card)? - What other structured data can be added (e.g., FAQ schema, BreadcrumbList)? - Are there any common error patterns in multilingual SEO that need attention? - What are some quick improvement directions for Core Web Vitals? - How should the internal linking strategy be planned? Please list the top 3-5 highest priority improvement suggestions first.
References

Extended Reading#

These are the resources that have actually been referred to and borrowed in the process.

writings Why is it important?
Apideck: Your MCP Server Is Eating Your Context Window Inspired by the analogy of "invisible forms of origin"
SEO for Astro: How to Make the Fastest Framework Also the Smartest The Complete Guide to Astro SEO Implementation
JSON-LD Blog Post Example BlogPosting schema reference implementation
Multilingual SEO and Hreflang Guide 67% Source of error rate data
How to Improve Core Web Vitals Specific methods for optimizing SSR performance
Conclusion

SEO is engineering, not metaphysics#

There is a reason for every decision and a lesson to be learned from every pitfall.
SEO for SSR Blogs isn't a matter of setting up meta tags and calling it a day - it's an ongoing, iterative engineering problem.

// Decision Links

Question 1: Dynamic articles not in sitemap
  →Manual Compensationsitemap-posts.xml

Question 2: SSR No Cache
  → Static Pageprerender + Dynamic PageSSR

Question 3: Multilingual SEO Error-prone
  →hreflang Bidirectional +x-default

Verification: Google Search Console Manual Submission + Monitoring

// Summarize
Astro SSR + Automated SEO pipeline
No missing records, no duplication, no delays.
✦ Copy Prompt