Technical SEO
    ReactSEOLovable

    Here's How I Made Lovable SEO-Friendly with Static Site Generation (SSG)

    React apps built with Lovable are fast and interactive - but search engines struggle with client-side rendering. Here's how I implemented Static Site Generation to get the best of both worlds.

    DK
    David Kloeber(he/him)January 31, 2026

    Melbourne-based performance marketing consultant helping B2B and e-commerce brands grow through Google Ads, SEO, and analytics.

    Executive Summary

    Lovable generates React Single Page Applications (SPAs) that rely on client-side rendering. While great for interactivity, this means search engines initially see an empty page until JavaScript executes.

    By implementing Static Site Generation (SSG), I pre-render each page to HTML at build time. Search engines now see fully-formed content immediately, while users still get the rich React experience once JavaScript loads.

    The Problem: Empty Pages in Search Console

    When I checked Google Search Console, it showed my homepage as essentially empty. The "View Crawled Page" feature revealed just a loading shell - no content, no headings, no text for Google to index.

    This is the classic SPA problem. The HTML file contains only <div id="root"></div> and a script tag. All the actual content lives in JavaScript bundles that must download and execute before anything appears. While Google can render JavaScript, it's a slower two-phase process that can hurt rankings.

    The Solution: Static Site Generation

    SSG pre-renders each route to a complete HTML file during the build process. When a crawler (or user) requests a page, they get real HTML content immediately - no JavaScript required for the initial view.

    SSG vs SSR: What's the Difference?

    Both approaches solve the same problem - getting HTML to the browser before JavaScript runs - but they work differently:

    Static Site Generation (SSG)

    • • HTML generated at build time
    • • Same HTML served to every visitor
    • • Fastest possible response times
    • • Perfect for content that doesn't change per-user
    • • Requires rebuild to update content

    Server-Side Rendering (SSR)

    • • HTML generated on each request
    • • Can personalise content per visitor
    • • Slightly slower (server processing time)
    • • Better for dynamic, user-specific content
    • • Content always fresh without rebuilds

    Why I chose SSG: My site is primarily static marketing content - service pages, articles, and a contact form. There's no per-user personalisation needed, so SSG gives me the fastest possible load times with zero server costs. The pages are pre-built and served directly from Netlify's CDN.

    Here's what I implemented to make this work with Lovable and Netlify:

    1. Server Entry Point

    Created entry-server.tsx using React's renderToString andStaticRouter to render components to HTML strings on the server.

    2. Node.js Build Script

    Built a custom build-ssg.mjs script that builds the client, builds the server entry, then renders every route to static HTML files.

    3. Dynamic Metadata with react-helmet-async

    Each page defines its own title, description, and Open Graph tags via Helmet. The SSG process extracts these and injects them into the HTML head - crucial for SEO and social sharing.

    4. No-JavaScript Fallback

    Implemented a no-js /js class toggle pattern so content remains visible even if JavaScript fails to load. Pre-applied visibility classes during SSG to ensure crawlers always see content.

    5. URL Normalisation

    Configured Netlify redirects to enforce non-trailing-slash URLs and prevent duplicate content issues. All canonical tags point to the normalised version.

    6. Client-Side Hydration

    Updated the client entry to use hydrateRoot in production instead of createRoot. This attaches React to the existing HTML rather than replacing it.

    Key Technical Challenges

    Browser API Polyfills

    React components often use localStorage,window, ornavigator. Since SSG runs in Node.js, I had to polyfill these APIs in the build script to prevent crashes.

    Single HelmetProvider

    A tricky bug: having multiple HelmetProvider wrappers breaks SSR metadata extraction. The solution was ensuring only the server entry's provider exists during rendering, with HelmetProvider.canUseDOM = false explicitly set.

    Animation Visibility

    Scroll animations that start invisible (opacity: 0) caused content to be hidden in the static HTML. The fix was pre-applying theis-visible class during SSG and using CSS selectors to handle the no-JS case.

    The Results

    • Full content in View Source - All page content, metadata, and structured data visible without JavaScript
    • Faster Time to First Contentful Paint - Content renders immediately without waiting for JS bundles
    • Proper Search Console indexing - Google now sees complete pages instead of empty shells
    • Working no-JS fallback - Content remains accessible even if JavaScript fails

    Try It Yourself

    Want to implement SSG on your own Lovable project? Copy this prompt and paste it into Lovable:

    I want to implement Static Site Generation (SSG) for my Lovable-built React app so that search engines can properly index my content. Please help me set up the following:
    
    1. Create a server entry point (src/entry-server.tsx) that uses React's renderToString and StaticRouter from react-router-dom/server to render pages to HTML strings.
    
    2. Create a Node.js build script (scripts/build-ssg.mjs) that:
       - Builds the client bundle with Vite
       - Builds the server entry with Vite SSR mode
       - Polyfills browser APIs (localStorage, window) for Node.js
       - Renders each route to static HTML files
       - Injects the rendered HTML and head tags into the template
    
    3. Configure react-helmet-async for dynamic per-page metadata:
       - Ensure only ONE HelmetProvider wraps the app
       - Set HelmetProvider.canUseDOM = false in the server entry
       - Extract and inject head tags during SSG
    
    4. Update src/main.tsx to use hydrateRoot instead of createRoot in production for proper hydration.
    
    5. Add a no-JS fallback so content remains visible if JavaScript fails:
       - Use a no-js/js class toggle pattern on the html element
       - Ensure scroll animations don't hide content in static HTML
    
    6. Configure Netlify (netlify.toml) to:
       - Run the SSG build script
       - Redirect trailing slashes to non-trailing (301)
       - Serve .html files for clean URLs
    
    Here are my current routes that need to be pre-rendered:
    [List your routes here, e.g. /, /about, /services/example]
    
    Please implement this step by step, ensuring each piece works before moving to the next.

    Note: Replace the placeholder routes with your actual page routes. This is a complex implementation that may take several iterations to get right - be patient and work through any errors step by step.

    Should You Implement SSG?

    Yes, if your Lovable app is a marketing site, blog, e-commerce store, or anything where organic search traffic matters. The implementation requires understanding React's server-side capabilities, but the SEO benefits are substantial.

    How to Test Your SSG Implementation

    Once you've deployed your SSG build, use these tools to verify everything is working correctly:

    View Page Source (Ctrl/Cmd + U)

    The simplest test. Right-click → "View Page Source" and check if your actual content, headings, and meta tags are visible in the raw HTML. If you only see <div id="root"></div>, SSG isn't working.

    Free • Built into every browser

    Pre-Rendering Checker

    This tool fetches your URL without executing JavaScript and shows you exactly what search engines see. Compare the "Original" view (no JS) vs "Rendered" view (with JS) - they should show the same content.

    technicalseo.com/tools/pre-rendering

    Google Search Console URL Inspection

    The ultimate test. Enter your URL in the inspection tool, then click "View Crawled Page" → "HTML" to see exactly what Googlebot captured. After deploying SSG, request re-indexing and check again in a few days.

    search.google.com/search-console

    Rich Results Test

    While primarily for testing structured data, this tool also shows you what Google sees when rendering your page. Check both the "HTML" and "Screenshot" tabs to verify content visibility.

    search.google.com/test/rich-results

    Command Line: curl or wget

    For developers: run curl https://yoursite.com in terminal. This fetches raw HTML without any JavaScript processing - exactly how most bots see your page.

    Free • Requires terminal access

    Pro tip: Test multiple pages, not just your homepage. Route-specific issues are common in SSG implementations - a missed route in your build script means that page reverts to client-side only.

    Need help with technical SEO?

    I help businesses implement proper tracking, analytics, and technical SEO foundations. If you're struggling with similar challenges, let's chat.

    Get in Touch

    Trusted by

    teams and organisations I work with

    SpinTel
    Latrobe Community Health Service
    Country Care Group
    Madewell Products
    Jacaranda
    Wiley
    SpinTel
    Latrobe Community Health Service
    Country Care Group
    Madewell Products
    Jacaranda
    Wiley
    SpinTel
    Latrobe Community Health Service
    Country Care Group
    Madewell Products
    Jacaranda
    Wiley
    Omni Group
    Country Road Group
    Streamtime
    Goldie + Ace
    Fizz Kidz
    National Theatre
    Omni Group
    Country Road Group
    Streamtime
    Goldie + Ace
    Fizz Kidz
    National Theatre
    Omni Group
    Country Road Group
    Streamtime
    Goldie + Ace
    Fizz Kidz
    National Theatre
    Little Red Trucks
    National Ballet School
    Switch Supply
    Teavision
    SpinTel
    Latrobe Community Health Service
    Little Red Trucks
    National Ballet School
    Switch Supply
    Teavision
    SpinTel
    Latrobe Community Health Service
    Little Red Trucks
    National Ballet School
    Switch Supply
    Teavision
    SpinTel
    Latrobe Community Health Service