React SDK Guide
Use @earlyseo/blog in React apps (Vite, Remix, SPA) with provider, components, and hooks.
Overview
This guide covers using EarlySEO in client-side React apps — Vite, Remix, or any SPA setup. For Next.js App Router, use the Next.js SDK Guide instead, which supports server components and the npx @earlyseo/blog init CLI scaffold.
Prerequisites
- A React project (Vite, Remix, Create React App, etc.)
- SDK integration enabled in EarlySEO (Dashboard → Integrations → SDK)
- Site ID from the SDK integration card
- At least one published article
1. Install package
npm install @earlyseo/blog2. Add provider
Wrap your app (or the blog section) with EarlySeoProvider. This makes the site ID and base path available to all child components.
import { EarlySeoProvider } from "@earlyseo/blog/react";
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<EarlySeoProvider siteId="your-site-id" basePath="/blog">
{children}
</EarlySeoProvider>
);
}| Prop | Type | Description |
|---|---|---|
siteId | string | Your EarlySEO site ID (required) |
basePath | string | URL prefix for blog routes (default: /blog) |
3. Render built-in components
Use the pre-built components for a zero-config blog UI:
import { BlogList, BlogPost, ArticleStyles } from "@earlyseo/blog/react";
// Blog listing page
export function BlogPage() {
return (
<>
<ArticleStyles />
<BlogList />
</>
);
}
// Single article page
export function BlogPostPage({ slug }: { slug: string }) {
return (
<>
<ArticleStyles />
<BlogPost slug={slug} />
</>
);
}| Component | Description |
|---|---|
ArticleStyles | Injects EarlySEO CSS styles into the page |
BlogList | Renders a paginated article list with links |
BlogPost | Renders a single article by slug |
4. Headless mode with hooks
Build a fully custom UI using the data hooks:
import { useArticles, useArticle } from "@earlyseo/blog/react";
export function CustomList() {
const { articles, loading } = useArticles();
if (loading) return <div>Loading...</div>;
return (
<div>
{articles.map((article) => (
<a key={article.slug} href={`/blog/${article.slug}`}>
<h3>{article.title}</h3>
<p>{article.metaDescription}</p>
</a>
))}
</div>
);
}
export function CustomPost({ slug }: { slug: string }) {
const { article, loading } = useArticle(slug);
if (loading) return <div>Loading...</div>;
if (!article) return <div>Not found</div>;
return <div dangerouslySetInnerHTML={{ __html: article.contentRawHtml }} />;
}| Hook | Returns | Description |
|---|---|---|
useArticles() | { articles, loading } | Fetches paginated article list |
useArticle(slug) | { article, loading } | Fetches a single article by slug |
How publishing works
- Publish an article from the EarlySEO dashboard
- CDN JSON files update automatically
- Your React app reads the updated JSON on the next fetch
- No rebuild or redeploy needed
Routing example (React Router)
import { Routes, Route } from "react-router-dom";
function App() {
return (
<EarlySeoProvider siteId="your-site-id" basePath="/blog">
<Routes>
<Route path="/blog" element={<BlogPage />} />
<Route path="/blog/:slug" element={<BlogPostRoute />} />
</Routes>
</EarlySeoProvider>
);
}
function BlogPostRoute() {
const { slug } = useParams();
return <BlogPostPage slug={slug!} />;
}Troubleshooting
No content returned
- Verify your
siteIdis correct - Confirm the integration type is SDK in the dashboard
- Confirm the article status is published
CORS issues
- Requests go directly to
media.earlyseo.com— no proxy needed - If using a custom proxy, ensure CORS headers are set
Inconsistent styling
- Always render
<ArticleStyles />before<BlogList />or<BlogPost /> - For fully custom styles, use
contentRawHtmlfrom the hooks and apply your own CSS
Need help?
- SDK Integration Setup
- Next.js SDK Guide (for server-rendered setups)
- SDK Troubleshooting
- Email team@earlyseo.com