└── README.md /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # πŸ“‘ Ultimate SEO Guide for Vibe Coding 4 | 5 | ### *Master React + TypeScript SEO with Production-Ready Code Examples* 6 | 7 | [![Vibe Coding](https://img.shields.io/badge/Vibe-Coding-purple?style=for-the-badge&logo=react)](https://github.com/markfulton/VibeCodingSEO) 8 | [![React](https://img.shields.io/badge/React-18+-61DAFB?style=for-the-badge&logo=react)](https://reactjs.org/) 9 | [![TypeScript](https://img.shields.io/badge/TypeScript-5+-3178C6?style=for-the-badge&logo=typescript)](https://www.typescriptlang.org/) 10 | [![SEO](https://img.shields.io/badge/SEO-Optimized-green?style=for-the-badge&logo=google)](https://developers.google.com/search) 11 | 12 | --- 13 | 14 | ### πŸ“ˆ **Get Your Vibe Coded Apps Ranked/Indexed on Search Engines** 15 | 16 | This comprehensive guide provides **practical, production-ready blueprints** for maximizing organic visibility in React + TypeScript applications. From SSR strategies to Core Web Vitals optimization, get **drop-in code patterns** you can implement today. 17 | 18 | ### πŸ’» **Join the Vibe Coding Community** 19 | 20 | 21 | 22 | 29 | 36 | 37 |
23 | 24 | Join Vibe Coding Skool 25 | 26 |
27 | Premium Courses & Live Sessions 28 |
30 | 31 | Join Facebook Group 32 | 33 |
34 | Largest Vibe Coding Community 35 |
38 | 39 | **πŸŽ“ [Vibe Coding is Life Skool](https://www.skool.com/vibe-coding-is-life/about?ref=456537abaf37491cbcc6976f3c26af41)** - Access exclusive courses, training sessions, live builds, and project downloads 40 | 41 | **πŸ‘₯ [Facebook Community](https://www.facebook.com/groups/vibecodinglife)** - Connect with 71,000+ developers in the largest Vibe Coding group 42 | 43 |
44 | 45 | --- 46 | 47 | ## πŸ“‹ Table of Contents 48 | 49 | - 🎯 [Core SEO Decisions That Move the Needle](#-core-seo-decisions-that-move-the-needle) 50 | - πŸ—οΈ [Making React Indexable](#️-making-react-indexable) 51 | - πŸ”— [URL Architecture & Routing](#-url-architecture--routing) 52 | - πŸ“Š [Route-Level Meta Management](#-route-level-meta-management) 53 | - 🏷️ [Structured Data & JSON-LD](#️-structured-data--json-ld) 54 | - πŸ€– [Crawling, Indexing & Sitemaps](#-crawling-indexing--sitemaps) 55 | - πŸ“„ [Pagination & Infinite Scroll](#-pagination--infinite-scroll) 56 | - ⚑ [Core Web Vitals Optimization](#-core-web-vitals-optimization) 57 | - 🌍 [Internationalization](#-internationalization) 58 | - πŸ“± [Social Sharing Previews](#-social-sharing-previews) 59 | - πŸš€ [Deployment & Headers](#-deployment--headers) 60 | - πŸ”§ [CI/CD SEO Guardrails](#-cicd-seo-guardrails) 61 | - πŸ“ [Quick Start Checklist](#-quick-start-checklist) 62 | - ⚠️ [Common Pitfalls & Solutions](#️-common-pitfalls--solutions) 63 | - 🏒 [CMS Integration Strategies](#-cms-integration-strategies) 64 | - πŸ› οΈ [Framework Recommendations](#️-framework-recommendations) 65 | - πŸ“š [Additional Resources](#-additional-resources) 66 | 67 | --- 68 | 69 | ## 🎯 Core SEO Decisions That Move the Needle 70 | 71 | > **React-specific decisions that maximize organic visibility** 72 | 73 | ### 1. πŸ—οΈ **Render Content as HTML** 74 | - **Prefer SSR/SSG or pre-rendering** so bots and users see real HTML fast 75 | - Google explicitly recommends SSR/static rendering over "dynamic rendering" user-agent workarounds 76 | - If you must ship a pure SPA, ensure every indexable view has a **unique URL that returns HTML** 77 | 78 | ### 2. πŸ”— **Use Crawlable Links and Stable URLs** 79 | - Google finds pages via `` β€” it **doesn't click buttons** to load more results 80 | - Google **ignores `#` fragments** for unique content 81 | - Use real `` links and real URLs 82 | 83 | ### 3. πŸ“„ **Canonicalization, Pagination & Parameters** 84 | - Set the canonical for each page (absolute URL) 85 | - Don't force every paginated URL to canonicalize to page 1 86 | - For sorted/filtered variants, either prevent indexing or keep them crawl-eligible but non-indexable 87 | 88 | ### 4. 🏷️ **Structured Data (JSON-LD)** 89 | - Use JSON-LD and follow Google's structured-data guidelines 90 | - Support Organization/LocalBusiness, Product/Service, FAQ, Breadcrumbs 91 | - If you generate it with JS, that's supportedβ€”just test with Rich Results 92 | 93 | ### 5. ⚑ **Core Web Vitals Are Ranking-Relevant** 94 | - As of **March 12, 2024, INP replaced FID** as a Core Web Vital 95 | - Monitor **LCP, CLS, INP** and optimize images, fonts, JS, and caching 96 | 97 | ### 6. πŸ€– **Crawl Controls & Sitemaps** 98 | - Use **meta robots / X-Robots-Tag** to control indexing 99 | - **robots.txt cannot "noindex"** a page 100 | - Keep **JS/CSS unblocked** 101 | - Supply an XML sitemap (50k URLs / 50 MB max per file) 102 | 103 | --- 104 | 105 | ## πŸ—οΈ Making React Indexable 106 | 107 | ### A. 🌟 **Best-Case: SSR/SSG (React 18 Streaming)** 108 | 109 | If your platform allows Node on the edge/origin, React 18's `renderToPipeableStream` reduces time-to-HTML and improves LCP. Combine with route-level meta and HTTP caching. 110 | 111 | ### B. πŸ“± **Pure SPA (Vite + React Router) with Pre-render** 112 | 113 | If SSR is truly impossible, **pre-render** public routes at build time: 114 | 115 | - βœ… Each page has a **static HTML shell** (title/description/LD+JSON) 116 | - βœ… Navigation uses real `` links (no button-driven routing) 117 | 118 | --- 119 | 120 | ## πŸ”— URL Architecture & Routing 121 | 122 | ### 🎯 **Essential Rules** 123 | 124 | - ❌ **No hash routing** β€” bots ignore `#` for uniqueness. Use History API URLs 125 | - βœ… Every indexable view must have a **unique, shareable URL** 126 | - βœ… Choose one hostname (e.g., `https://www.example.com`), enforce **HTTPS + 301s** 127 | - βœ… Normalize trailing slashes/case; produce a single canonical per page 128 | - βœ… **Use absolute canonicals** 129 | 130 | --- 131 | 132 | ## πŸ“Š Route-Level Meta Management 133 | 134 | ### πŸ› οΈ **Robust React + TypeScript Pattern** 135 | 136 | Use **React Router v6 "data routers"** with a `handle.seo` contract and **react-helmet-async** to generate unique metadata per route. 137 | 138 | ```tsx 139 | // src/seo/SEO.tsx 140 | import { Helmet } from 'react-helmet-async'; 141 | 142 | export type SEOConfig = { 143 | title?: string; 144 | description?: string; 145 | canonical?: string; // absolute or site-relative 146 | robots?: string; // e.g., "index,follow" or "noindex" 147 | og?: { type?: string; image?: string | null }; 148 | twitter?: { card?: 'summary' | 'summary_large_image'; site?: string; creator?: string }; 149 | schema?: Record | Record[]; 150 | }; 151 | 152 | const SITE_URL = 'https://www.example.com'; 153 | 154 | export function SEO(cfg: SEOConfig) { 155 | const { 156 | title, description, robots = 'index,follow', og = {}, twitter = {}, schema 157 | } = cfg; 158 | const canonicalUrl = 159 | cfg.canonical?.startsWith('http') 160 | ? cfg.canonical 161 | : `${SITE_URL}${cfg.canonical || (typeof window !== 'undefined' ? window.location.pathname : '/')}`; 162 | 163 | return ( 164 | 165 | {title && {title}} 166 | {description && } 167 | 168 | 169 | 170 | {/* Open Graph / Twitter */} 171 | 172 | 173 | {title && } 174 | {description && } 175 | {og.image && } 176 | 177 | {twitter.site && } 178 | {twitter.creator && } 179 | 180 | {/* JSON-LD */} 181 | {schema && (Array.isArray(schema) ? schema : [schema]).map((obj, i) => ( 182 |