Note
This article was translated by AI
I was keen on using Next.js's Static Site Generation (SSG). I chose the popular Tailwind Next.js Starter Blog as the base for my personal blog but ran into many issue when adding internationalization (i18n).
After trying several approaches, I finally achieved stable and efficient i18n support using next-intl, which led to this project. This is a ready-to-use blog template that lets you easily set up a multilingual blog, even with little coding experience. I also hope this project serves as a good reference for combining SSG and i18n.
Building on the core features of the Tailwind Next.js Starter Blog, this project integrates i18n and improves the development process. Key features include:
- Excellent User Experience: Near-perfect Lighthouse scores
- Out-of-the-Box i18n: Integrated with next-intl, supporting SSG.
- Automatically detects the user's browser language.
- Saves the user's language preference via a Cookie (supports configurable expiration for compliance; defaults to a session cookie).
- Includes translations for Simplified Chinese, English, and Japanese.
- i18n SEO Optimization:
- Automatically generates
<link rel="alternate" hreflang="...">tags,Metadata, andOpen Graphtags. - Uses next-sitemap to generate
robots.txtand multilingualsitemapfiles.
- Automatically generates
- Multilingual RSS/Atom Feed Support: Uses feed to generate separate static feed files for each language.
- Modern Styling: Based on Tailwind CSS v4.1 for easy customization.
- Zero-Config In-Site Search: Modified from
pliny/search, powered byKBar. - Image Loading Optimization: Automatically create WebP copies for local PNG and JPG images to optimize image loading in modern browsers. Use SVG placeholders to enhance user experience during image loading. For local article banner images in PNG and JPG formats, you do not need to manually set the path for the WebP version.
- Modern Markdown Authoring:
- Supports MDX, allowing you to embed JSX/React components directly in Markdown.
- Processes Markdown/MDX files with
contentlayer2. - Syntax highlighting powered by
rehype-pretty-code, including line numbers and highlighting. Code copying is adapted frompliny/ui/Pre. - Math formula rendering with KaTeX.
- Supports GitHub-style alerts, implemented via remark-github-blockquote-alert.
- Support Disqus through DisqusJS. It can render Disqus comments in regions with internet censorship.
Features removed from the original template: Newsletter、 website analytics, citation and reference.
-
Clone the repository
git clone https://github.com/Aaakul/next-ssg-i18n-blog-starter.git
-
Install dependencies
cd next-ssg-i18n-blog-starter npm install -
Configure basic site settings Edit
./data/SiteConfig.mjsto set your website's basic information and social media links. -
Localize content Update the following fields in
./i18n/messages/*.json:header_title: Navigation bar titlesite_title: Website titlesite_description: Website description
-
Replace icons and avatar Update the following files:
- Site icons:
./app/favicon.ico,./app/apple-touch.png,./public/favicon.svg - Default author avatar:
./public/static/images/avatar.svg - Open Graph and Twitter cards image:
./public/static/images/twitter-card.jpg
- Site icons:
-
Customize the projects page Edit
./data/projectsData.tsto update the projects descriptions. -
Configure author information Edit the corresponding language file at
./data/authors/.../default.md(see "Markdown / MDX - Author Page" section). -
Add blog posts Create new Markdown files in the
./data/blog/directory (refer to "Markdown / MDX - Articles" section).
Start the development server using Turbopack:
npm run devNote
If you're editing Markdown files or modifying Contentlayer2 config and need hot reloading, use Webpack mode instead:
npm run dev:webpackTip
To manually build Contentlayer2 content:
npm run contentlayerTo enable Disqus, please refer to ./.env.example to create a .env file containing the Disqus configuration, and make sure that isEnableDisqusJS in SiteConfig.mjs is set to true.
The project includes built-in support for Simplified Chinese (zh), English (en), and Japanese (ja). Translation files are in ./i18n/messages/. You can improve these or add more languages.
For information about Translation files, please refer to the next-intl documentation
-
Styling
Adjust the overall style easily via./tailwind.config.mjsand./styles/*.cssto change Tailwind v4 configuration and CSS styles.
To change the theme color (Primary colour), please modify--color-primary-*: var(--color-sky-*);in./styles/global.cssand replaceskywith another color. -
MDX Components
Register custom React components incomponents/MDXComponents.tsxto use them in.mdxor.mdfiles. Note: Use default exports for components to avoid a known Next.js issue. -
Navigation Bar
Modify./components/Header.tsxto customize the top navigation links.
The project uses Contentlayer2 to process .md and .mdx files.
Frontmatter follows the Hugo standard format. See ./contentlayer.config.ts for detailed field definitions.
Required fields:
name: string
language: string // Must match a language configured in `SiteConfig`Optional fields:
avatar: string
occupation: string
company: string
mail: string
bilibili: string
youtube: string
mastodon: string
x: string
twitter: string
facebook: string
linkedin: string
threads: string
instagram: string
medium: string
bluesky: string
github: stringRequired fields:
title: string
date: string // ISO 8601 format. e.g., '2025-01-01T08:35:00Z'
translationKey: string // Used to link articles across languages
language: string // Must match a language configured in `SiteConfig`Optional fields:
tags: string[]
lastmod: string // Last modified date
draft: boolean // If true, the article will not be built in production
summary: string // Article summary
image: string // The URL of the image used for the article's top banner, Open Graph, and Twitter Card
authors: string[] // Filenames under `./data/authors/`. Defaults to ['default']
layout: string // Page layout. Defaults to 'PostLayout'
isCanonical: boolean // If true, adds <link rel="alternate" hreflang="x-default" ...> tag. Defaults to false
categories: string[] // Article categories
enableComments: boolean // Default to `true`Example: Article with all Frontmatter fields
---
title: 'Introducing Next SSG i18n Blog Starter'
summary: 'This article introduces the Next SSG i18n Blog Starter, a ready-to-use Next.js blog template that supports static site generation and multiple languages'
translationKey: 'intro'
date: '2025-11-11T07:45:00Z'
lastmod: '2025-11-19T07:30:00Z'
tags: ['next', 'coding', 'guide']
categories: ['sample']
language: 'en'
authors: ['default', 'test']
image: '/static/images/twitter-card.jpg'
isCanonical: false
layout: 'PostLayout'
enableComments: true
---
# H1 Title
Some content...
{/* Built-in Table of Contents component */}
<TOCInline toc={props.toc} exclude="section to be excluded" toHeading={2} />Important
The translationKey field is vital for linking multilingual versions of an article. Ensure all language versions of the same content use the same value.
This project is built for SSG and deploys easily to any static hosting platform, such as GitHub Pages, Cloudflare Pages, AWS S3, or Firebase Hosting.
Build with Turbopack:
npm run exportAfter building, upload the out directory to your static hosting service.
After building, you can preview the site locally using:
npx serve outThen open the URL shown in the terminal (default: http://localhost:3000) in your browser.
If basePath is configured (e.g., '/blog'), the files in ./out need to be copied to ./out/blog
A .github/workflows/pages.yml configuration file will be available soon. Once enabled, it will automatically build and deploy to GitHub Pages.
- Fork this repository.
- Log in to the Cloudflare Dashboard, and go to Workers and Pages.
- Click Create application → Pages → Import from Git, connect your GitHub account, and select your forked repository.
- Set up the build configuration:
- Build command:
npm run export - Build output directory:
out - Environment variables (advanced) → Add variable: Variable name:
SITE_URL, Value:https://(yourdomain)
- Build command:
- Click Save and Deploy. Cloudflare will complete the first build and deployment automatically.
Every subsequent code push will automatically trigger a new build on Cloudflare Pages.
Set the basePath field in ./data/SiteConfig.mjs if you're deploying to a subdirectory (e.g., https://example.com/myblog/).
- Add Command Palette with kbar - Modern Next.js Blog Series #26 (Traditional Chinese page)
- How can I customize the
kbarsearch?
This project is derived from:
Both created by Timothy Lin (timlrx). Thank you for your invaluable contribution to the open-source community.
This project is licensed under the MIT License.