npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ssr-seo

v1.0.1

Published

Make your React SPA SEO-friendly without SSR complexity. Automatically generates static HTML snapshots for search engine crawlers.

Readme

🚀 SSR-SEO

npm version npm downloads license TypeScript

Make your React SPA SEO-friendly without SSR complexity. SSR-SEO automatically generates static HTML snapshots for search engine crawlers while serving your dynamic React app to users.


🔥 Project Status: Early / New

⚠️ This is a brand new project and actively evolving.

SSR-SEO is in early-stage development. APIs, defaults, and integration patterns may still change as real-world usage expands.

That said:

  • The core snapshot + bot-detection logic is stable
  • The Lovable integration pattern is intentional
  • The guardrails below are important

If you hit something odd, that is expected at this stage. Please report it.

👉 Issues & feedback:
https://github.com/Azerax/ssr-seo-tracker/issues


✨ Features

  • 🤖 Smart Bot Detection - Automatically identifies search engine crawlers
  • 📸 HTML Snapshots - Generates static HTML for perfect SEO indexing
  • 🗺️ Dynamic Sitemap - Auto-generates sitemaps from your routes
  • 🤖 Robots.txt Management - Configure crawler access rules
  • 📊 Monitoring Dashboard - Track SEO health and issues
  • 🔧 Auto-Fix - Automatically resolves common SEO issues
  • 🎨 Beautiful UI - Pre-built dashboard components
  • 📦 Zero Config - Works out of the box with sensible defaults

⚠️ Important: What This Package Does NOT Do

  • Does NOT create routes - You own your routing; we don't inject anything
  • Does NOT take over / - Your app's root route remains yours
  • Dashboard is opt-in - Add /ssr-seo/* routes only if you want the dashboard UI

📦 Installation

npm install ssr-seo
# or
yarn add ssr-seo
# or
pnpm add ssr-seo

Peer Dependencies

SSR-SEO requires React as a peer dependency:

npm install react react-dom

🌐 Lovable Demo (Hackathon Build)

A live Lovable demo of SSR-SEO is available here:

https://important-cats.lovable.app/ssr-seo/status

Notes:

  • Created during the Lovable hackathon the weekend of Jan 2
  • Currently under freeze while judges review submissions
  • May lag behind the latest package changes

🚀 Integration Patterns

SSR-SEO supports two integration patterns depending on your app architecture.


Pattern 1: Stand-alone (Lovable-style)

Best for apps built with Lovable or where you want SSR-SEO to manage the Supabase connection.

Step 1: Set environment variables

VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key

Step 2: Wrap your app

import { SSRSEOProvider } from 'ssr-seo';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <SSRSEOProvider>
        <Routes>
          {/* YOUR routes - SSR-SEO does not create or own any routes */}
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </SSRSEOProvider>
    </BrowserRouter>
  );
}

SSR-SEO will automatically create a Supabase client from the environment variables.


Pattern 2: Controlled (Advanced Apps)

Best for apps that already have a Supabase client or need full control over the connection.

Step 1: Create your Supabase client

import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  'https://your-project.supabase.co',
  'your-anon-key'
);

Step 2: Pass the client to SSRSEOProvider

import { SSRSEOProvider } from 'ssr-seo';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { supabase } from './lib/supabase';

function App() {
  return (
    <BrowserRouter>
      <SSRSEOProvider supabaseClient={supabase}>
        <Routes>
          {/* YOUR routes - SSR-SEO does not create or own any routes */}
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </SSRSEOProvider>
    </BrowserRouter>
  );
}

Optional: Add Dashboard Routes

The dashboard is completely opt-in. If you want the monitoring UI, add the routes yourself:

import { SSRSEOProvider, SSRSEODashboardRoutes } from 'ssr-seo';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <SSRSEOProvider>
        <Routes>
          {/* Your routes */}
          <Route path="/" element={<Home />} />

          {/* Opt-in: SSR-SEO Dashboard under /ssr-seo/* */}
          {SSRSEODashboardRoutes}
        </Routes>
      </SSRSEOProvider>
    </BrowserRouter>
  );
}

Dashboard routes provided:

| Route | Description | |------|-------------| | /ssr-seo/status | Setup verification and health checks | | /ssr-seo/config | SEO configuration and settings | | /ssr-seo/monitoring | Real-time monitoring and alerts |


🤖 Important: Lovable Integration Guardrails (READ THIS FIRST)

If you are using Lovable, this section is critical.

The actual problem

Lovable will not run init the way you expect. Instead, it tries to "do it itself" by scaffolding and restructuring, and that breaks SSR-SEO.

The good news: when this happens, the damage is usually contained to the /ssr-seo directory, so it is fixable. The bad news: undoing it costs Lovable prompts/credits.

✅ The correct approach

You must explicitly prompt Lovable to read and implement LOVABLE.md exactly as written.

Also tell Lovable:

  • Do not scaffold or restructure the project
  • Do not try to re-initialize anything
  • Follow the steps in LOVABLE.md exactly

✅ Safe Lovable prompt (copy/paste)

Use this prompt verbatim:

Read LOVABLE.md and implement it exactly as written.
Do not scaffold or restructure the project.
Do not "init" the project in your own way.
Follow the LOVABLE.md steps exactly and only change what it instructs.

⚠️ What happens if you skip this

If Lovable scaffolds on its own:

  • It can break SSR-SEO (usually inside /ssr-seo)
  • It is fixable, but it costs prompts and credits to undo
  • That time and cost is avoidable if LOVABLE.md is followed first

📄 LOVABLE.md is Required Reading

If you are using Lovable:

  • LOVABLE.md is not optional
  • It exists specifically to prevent tool-driven breakage
  • Skipping it is the fastest way to lose time and credits

📖 API Reference

SSRSEOProvider

The main provider component that wraps your application.

interface SSRSEOProviderProps {
  children: React.ReactNode;

  // Supabase connection (choose one):
  supabaseClient?: SupabaseClient;     // Pass your own client (Pattern 2)
  supabaseUrl?: string;                // Or provide URL + key
  supabaseAnonKey?: string;            // (auto-reads from VITE_* env vars)

  // Behavior options:
  autoSetup?: boolean;        // Auto-initialize on mount (default: true)
  autoScan?: boolean;         // Auto-scan for routes (default: true)
  scanIntervalHours?: number; // Hours between scans (default: 24)
  dashboardBasePath?: string; // Dashboard URL base (default: '/ssr-seo')
}

useSSRSEO Hook

Access SEO context from any component.

import { useSSRSEO } from 'ssr-seo';

function MyComponent() {
  const {
    supabase,              // The Supabase client (or null if not configured)
    isSupabaseConnected,   // Boolean: is Supabase available?
    isBot,                 // Is current request from a bot?
    config,                // Current SEO config
    refreshSnapshots,      // Trigger snapshot refresh
    runScan                // Run an SEO scan
  } = useSSRSEO();

  if (!isSupabaseConnected) {
    return <div>Please configure Supabase to use SEO features</div>;
  }

  return (
    <div>
      {isBot ? 'Bot detected!' : 'Human user'}
      <button onClick={runScan}>Run SEO Scan</button>
    </div>
  );
}

SEOHead Component

Set page-specific SEO metadata.

import { SEOHead } from 'ssr-seo';

function BlogPost({ post }) {
  return (
    <>
      <SEOHead
        title={post.title}
        description={post.excerpt}
        keywords={post.tags}
        ogImage={post.image}
        ogType="article"
        canonicalUrl={`https://mysite.com/blog/${post.slug}`}
      />
      <article>{/* content */}</article>
    </>
  );
}

Utility Functions

import {
  detectBot,
  generateSitemap,
  generateRobotsTxt,
  validateMetaDescription,
  validateTitle,
} from 'ssr-seo';

const isBot = detectBot(userAgent);
const sitemap = await generateSitemap('https://mysite.com');

const titleResult = validateTitle('My Page Title');
// { valid: true, length: 13, issues: [] }

⚙️ Database Setup

SSR-SEO uses Supabase for data storage. Required tables:

  • seo_snapshots - Stores HTML snapshots
  • seo_config - Stores configuration
  • seo_monitoring - Stores scan results
  • seo_alerts - Stores SEO issues

If using the dashboard, navigate to /ssr-seo/status to verify your setup. The dashboard will show you what is missing.


🎯 Common Use Cases

E-commerce Product Pages

import { SEOHead } from 'ssr-seo';

function ProductPage({ product }) {
  return (
    <>
      <SEOHead
        title={`${product.name} | My Store`}
        description={product.description.slice(0, 160)}
        ogImage={product.images[0]}
        ogType="product"
      />
      <ProductDetails product={product} />
    </>
  );
}

Blog with Dynamic Content

import { useSSRSEO } from 'ssr-seo';

function BlogLayout({ children }) {
  const { refreshSnapshots, isSupabaseConnected } = useSSRSEO();

  useEffect(() => {
    if (newPostPublished && isSupabaseConnected) {
      refreshSnapshots();
    }
  }, [newPostPublished, isSupabaseConnected]);

  return <div>{children}</div>;
}

Manual Snapshot Generation

import { generateSnapshot } from 'ssr-seo';

async function createSnapshot(path: string) {
  const snapshot = await generateSnapshot(path);
  console.log('Generated snapshot:', snapshot.metadata);
}

🔧 Troubleshooting

"Supabase Not Configured" Error

This appears when SSR-SEO cannot connect to Supabase. Fix it by:

  • Pattern 1: Set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY env vars
  • Pattern 2: Pass supabaseClient prop to SSRSEOProvider

Snapshots Not Generating

  • Verify Supabase connection at /ssr-seo/status
  • Check that routes are being detected
  • Ensure your components render content synchronously
  • Check browser console for errors

Bot Detection Not Working

import { detectBot } from 'ssr-seo';

console.log(detectBot('Googlebot/2.1')); // true
console.log(detectBot('Mozilla/5.0'));   // false

Dashboard Not Loading

  • Ensure SSRSEODashboardRoutes is added to your Routes
  • Check you are navigating to /ssr-seo/status
  • Verify Supabase is configured (see above)

🐞 Issues & Feedback

This project uses a dedicated public issue tracker.

👉 Report bugs, request features, or share feedback here:
https://github.com/Azerax/ssr-seo-tracker/issues

Note: The source code is maintained in a private repository. This repo exists only for issues and feedback.


📄 License

MIT © Scott Holmes


🔗 Links

  • NPM Package: https://www.npmjs.com/package/ssr-seo
  • Issue Tracker: https://github.com/Azerax/ssr-seo-tracker/issues
  • Changelog: ./CHANGELOG.md