How to Display Blog Post Count on Docusaurus Homepage
Many developers using Docusaurus want to display the number of blog posts they have-especially on their homepage. While this may sound trivial, doing it the right way (that works on both your local dev and production builds like Vercel) requires some thought.
Hereβs a simple and reliable way to implement this-no hacks, no unstable APIs, just clean engineering.
π‘ Problemβ
You canβt just use internal hooks like useBlogPosts()
inside your homepage (src/pages/index.js
), because Docusaurus statically renders this file during build. And those hooks arenβt available at build time, which will cause your build to fail-especially on platforms like Vercel.
β Solution: Use a Build-Time Scriptβ
Weβll write a small Node.js script that:
- Counts all
.md
and.mdx
files inside yourblog/
folder - Writes that number into a JSON file
- Imports that JSON at build-time to show the count
π§± Step-by-Step Guideβ
1. Create a Scriptβ
In your project root, create a new directory: mkdir scripts
Inside it, create blogStats.js
:
// scripts/blogStats.js
const fs = require('fs');
const path = require('path');
const blogDir = path.join(__dirname, '..', 'blog');
function getMarkdownFiles(dir) {
if (!fs.existsSync(dir)) return [];
return fs
.readdirSync(dir)
.filter(file => file.endsWith('.md') || file.endsWith('.mdx'));
}
const count = getMarkdownFiles(blogDir).length;
const outputPath = path.join(__dirname, '..', 'src', 'data');
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath, { recursive: true });
}
fs.writeFileSync(
path.join(outputPath, 'blogStats.json'),
JSON.stringify({ count }, null, 2)
);
console.log(`β
Blog post count: ${count}`);
2. Open package.json and update the scripts blockβ
{
"scripts": {
"build": "npm run count:blogs && docusaurus build",
"count:blogs": "node scripts/blogStats.js",
"start": "docusaurus start",
"dev": "docusaurus start",
...
}
}
Now, every time you run npm run build, the script will generate src/data/blogStats.json before Docusaurus builds the site.
3. Create a Reusable Componentβ
Create src/components/BlogPostCount.js:
import React from 'react';
import blogStats from '../data/blogStats.json';
export default function BlogPostCount() {
return (
<p className="padding-horiz--md">
π Total Blog Posts: <strong>{blogStats.count}</strong>
</p>
);
}
4. Use It in Your Homepageβ
Open src/pages/index.js (or src/pages/index.tsx) and use the component:
import React from 'react';
import Layout from '@theme/Layout';
import BlogPostCount from '../components/BlogPostCount';
export default function Home() {
return (
<Layout title="Welcome">
<main className="margin-vert--xl">
<h1>Hello π</h1>
<BlogPostCount />
</main>
</Layout>
);
}
Now when you build and deploy your site, the count will be visible on the homepage and updated automatically.
π Production-Readyβ
This solution:
- Works with Server-Side Rendering (SSR)
- Works with Vercel, Netlify, or static file hosting
- Avoids unstable internal Docusaurus APIs
- Can be extended to collect other data (e.g., blog titles, tags)
β Example Outputβ
π Total Blog Posts: 14
π Final Thoughtsβ
This is a small detail, but itβs these kinds of touches that make your static site feel alive and professional. As your content grows, your site keeps up-automatically.