babylovegrowth-next-js-blog
v0.2.2
Published
Read your published BabyLoveGrowth articles server-side and render them as a blog on your own Next.js (App Router) site.
Maintainers
Readme
babylovegrowth-next-js-blog
Read your published BabyLoveGrowth articles server-side and render them as a blog on your own Next.js (App Router) site — with cached static rendering, SEO metadata, tag pages, and a sitemap.
This package is a small, dependency-free read client. Scaffold the matching starter blog with npx babylovegrowth-next-js-blog init (or copy /starter by hand) to get a complete blog in minutes.
Keep your API key server-side only. Never expose
BABYLOVEGROWTH_BLOG_API_KEYwith aNEXT_PUBLIC_prefix or read it from client components.
Install
npm install babylovegrowth-next-js-blogRequires Node.js 18.17+ and a Next.js App Router project.
Environment
Create a .env.local with the integration key from Settings → Integrations → Next.js Blog in your BabyLoveGrowth dashboard:
BABYLOVEGROWTH_BLOG_API_KEY=your_api_keyOptional, read by the starter:
NEXT_PUBLIC_SITE_URL— your site's URL; makes the sitemap and canonical URLs absolute.BABYLOVEGROWTH_BLOG_API_URL— override the API base (e.g. a staging backend). Defaults to production.
Quick start
Create a single shared client and reuse it from Server Components, route handlers, generateMetadata, and generateStaticParams:
// app/blog/lib/blog-client.ts
import { BlogClient } from "babylovegrowth-next-js-blog";
export const blog = new BlogClient({
apiKey: process.env.BABYLOVEGROWTH_BLOG_API_KEY,
// Revalidate once per day in production, near-instantly in development.
revalidate: process.env.NODE_ENV === "development" ? 10 : 86400,
});// app/blog/page.tsx
import { blog } from "./lib/blog-client";
export const revalidate = 86400;
export default async function BlogIndex() {
const articles = await blog.getAllArticles();
return (
<ul>
{articles.map((a) => (
<li key={a.id}>
<a href={`/blog/${a.slug}`}>{a.title}</a>
</li>
))}
</ul>
);
}// app/blog/[slug]/page.tsx
import { notFound } from "next/navigation";
import { blog } from "../lib/blog-client";
export default async function Article({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const article = await blog.getArticleBySlug(slug);
if (!article) notFound();
return <div dangerouslySetInnerHTML={{ __html: article.content_html }} />;
}Use the starter blog
The fastest path to a full blog is to scaffold the starter with one command, from your Next.js project root:
npx babylovegrowth-next-js-blog initThis copies the blog routes, components, sitemap, and styles into your app/blog (or src/app/blog) directory. Pass a target like npx babylovegrowth-next-js-blog init src/app to override auto-detection, or --force to overwrite an existing blog/ folder. Then:
- Install the client:
npm install babylovegrowth-next-js-blog. - Set
BABYLOVEGROWTH_BLOG_API_KEYin.env.local. - Allow your article image host in
next.config.ts(see below). - Run
npm run devand open/blog.
Prefer to copy by hand? The same files live in the
starter/app/blogfolder of this repo.
The starter uses Tailwind CSS utility classes. If your app does not use Tailwind, copy the markup and replace the classes with your own CSS, or rely on the included blog-content.css.
Allow remote article images
The starter renders article listing thumbnails with next/image. Add your article image host to next.config.ts:
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [{ protocol: "https", hostname: "*" }],
},
};
export default nextConfig;Or replace the next/image usage with a plain <img> tag.
Routes included (starter)
| Route | Description |
| ------------------- | ---------------------------------------------------- |
| /blog | Paginated article listing |
| /blog/[slug] | Server-rendered article page with metadata + JSON-LD |
| /blog/tag/[slug] | Tag-filtered article listing |
| /blog/sitemap.xml | Dynamic blog sitemap |
Caching & update timing
The client passes a revalidate window to every fetch via Next.js' next.revalidate option, and each starter route also exports revalidate. In production this defaults to one day; in development, set a low value for fast iteration.
- Published article responses are read with daily ISR caching by default.
- Publishing in BabyLoveGrowth clears the API-side cache immediately, but your Next.js site keeps its own ISR cache — visible updates can take up to a day.
- Redeploy or add on-demand revalidation if you need updates to appear sooner.
Pass revalidate: false to opt out of caching (sends cache: 'no-store').
API reference
new BlogClient(options)
| Option | Type | Default |
| ------------ | ----------------- | --------------------------------------------------- |
| apiKey | string | process.env.BABYLOVEGROWTH_BLOG_API_KEY |
| baseUrl | string | https://api.babylovegrowth.ai/api/integrations/v1 |
| revalidate | number \| false | 86400 |
| fetch | typeof fetch | global fetch |
Methods
listArticles({ limit?, offset?, publishedOnly? })→BlogArticleSummary[]— one page (max 50), newest first.getAllArticles({ publishedOnly? })→BlogArticleSummary[]— every article (pages internally).getArticleBySlug(slug)→BlogArticle | null— full article by slug.getArticleById(id)→BlogArticle | null— full article by id.getTags()→BlogTag[]— count-ranked tags derived from article keywords.getArticlesByTag(tagSlug)→BlogArticleSummary[]— articles for a tag.getSitemapEntries()→BlogSitemapEntry[]— slugs + timestamps for a sitemap.
Helpers: slugify, readingTimeMinutes, stripToText, deriveTags.
What gets synced
List, tag, and sitemap requests return summary fields. The full article HTML and Markdown are loaded only when you fetch a single article.
- Title and slug
- Meta description and excerpt
- Article HTML and Markdown (article pages only)
- Featured image URL
- Keywords (used to derive tags) and language code
- Created and updated timestamps
jsonLd/faqJsonLdschema markup
Notes for AI coding agents
If you ask an AI coding tool to add this to an existing Next.js site:
- Keep all
BlogClientcalls inside Server Components, route handlers, or server utilities. - Read the key only from
BABYLOVEGROWTH_BLOG_API_KEY— never in client components or browser-visible JS. - Render article HTML with
dangerouslySetInnerHTML. - Use static or ISR rendering (
export const revalidate) for cached article content.
License
MIT
