A custom Next.js blog starter for use with create next app
. This starter design is based on the original blog starter provided by Next, but includes many extra features and performance improvements that are nice to have right out of the box.
Run this in your terminal to get started:
npx create-next-app --example https://github.com/sandypockets/nextjs-blog-starter/tree/main nextjs-blog-starter
Was this blog starter what you were looking for?
- Preview
- Live demo
- Deploy your own
- Built with
- Core features
- Get started
- Customize code syntax highlighting
- Dependencies
- How it works
- Contributing
- Screenshots
Preview the example live on StackBlitz:
Check out the live demo at blog-starter.sandypockets.dev, or see it in production as my actual blog at sandypockets.dev, generated using create-next-app
Deploy the example using Vercel:
- Write articles in markdown
- Markdown is already styled. Just start writing.
- Dark mode based on OS preference, with toggle to manually change.
- Google Analytics
- Email contact form (using SendGrid)
- Tailwind CSS v3.0
- Preformatted code syntax highlighting
- Priority image downloads for content above the fold, deferred downloads for below it
- Automatically generated sitemap and robots.txt
- Automatically generated RSS feed
- Storybook.js
This README will guide you through the basic set up. However, please refer to the blog posts in the live demo for more information. Don't worry, no lorem ipsums here. Each post contains real, actually helpful content.
Built and tested with Node v20.11.1
- Bootstrap this starter using
create next app
.
npx create-next-app --example https://github.com/sandypockets/nextjs-blog-starter/tree/main nextjs-blog-starter
- Change into the new project directory and install dependencies.
cd nextjs-blog-starter && npm install
- Start the development server.
npm run dev
- Once the server is running, visit http://localhost:3000 in your browser.
- Set up constant variables, and prepare to generate a sitemap.
- Set up Google Analytics
- Set up SendGrid.
Set up each of the constants, much like you would a .env
, in the lib/constants.js
file.
export const EXAMPLE_PATH = 'blog-starter'
export const CMS_NAME = 'Markdown'
export const HOME_OG_IMAGE_URL = 'https://og-image.vercel.app/Next.js%20Blog%20Starter%20Example.png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg'
export const BLOG_NAME = 'Next.js Blog Starter'
export const KEYWORDS = 'starter, blog, next.js, template'
export const DESCRIPTION = 'A starter blog template for Next.js'
export const AUTHOR = 'sandypockets'
export const LANG = 'en-CA'
export const GITHUB_REPO = 'https://github.com/sandypockets'
Sitemaps are an important part of SEO. This section walks through adding your base URL to the sitemap generator. The generator runs automatically after each build, generating a new sitemap each time you update your blog.
The generated sitemap can be found in public/sitemap.xml
. This command also generates a new public/robots.txt
file.
- Open the
scripts/generate.sitemap.mjs
file. - On Line 5, replace
https://blog-starter.sandypockets.dev
with your own blog's website. - On Line 6, replace
en-CA
with your preferred locale (en-UK
,en-US
, etc.). This is used to determine the format of the date stamp in the sitemap.
When you're ready to test it:
- Run
npm run build
- Check the
public/
directory for thesitemap.xml
file androbots.txt
file. - Run
npm run start
- Visit
http://localhost:3000/sitemap.xml
If you see the xml sitemap, then it was successful.
An RSS feed is available for the blog at /feed.xml
. However, you must first configure the RSS generator to use your own URL.
- Open the
scripts/generate-rss.mjs
file. - On Line 7, replace the
https://blog-starter.sandypockets.dev
value ofBLOG_URL
with your own.
When you're ready to test it:
- Run
npm run build
- Check the
public/
directory for thefeed.xml
file. - Run
npm run start
- Visit
http://localhost:3000/feed.xml
If you see the xml RSS feed, then it was successful.
You will need to have your Google tag ID. If you do not have one, or do not have a Google Analytics account, you can sign up at analytics.google.com
- Create a copy of the
.env.local.example
file, and name it.env.local
. To do so in the terminal, run:
cp .env.local.example .env.local
- Grab your Google tag ID from your Analytics account, and replace the
G-XXXXXXXXXX
in the new.env.local
file you just created.
You will need a free SendGrid account, which allows you to send up to 100 emails each day.
- Get your SendGrid API key from your SendGrid account.
- Open the
.env.local
file that you created when setting up Google Analytics. - Replace
REPLACE-WITH-YOUR-API-KEY
with your actual API key from SendGrid.
When you use inline code or codeblocks on your blog, they'll be highlighted with the Dracula theme style, like this:
However, you can choose from over 38 other themes that are ready to go right out of the box.
- Open the
pages/_app.js
file. - On Line 5, note the import of
'prism-themes/themes/prism-dracula.css'
- To change the theme, simply replace the
prism-dracula.css
portion with the name of the new theme file as shown on this page.
For example, if you want to use the prism-duotone-sea
theme, then adjust the import statement on Line 5 to be import 'prism-themes/themes/prism-duotone-sea.css'
- @headlessui/react: ^1.7.18
- @heroicons/react: ^2.1.3
- @sendgrid/mail: ^8.1.1
- @tailwindcss/forms: ^0.5.7
- axios: ^1.6.8
- classnames: 2.2.6
- date-fns: 3.6.0
- gray-matter: 4.0.3
- next: latest
- prism-themes: ^1.9.0
- react: ^18.2.0
- react-dom: 18.2.0
- remark: 15.0.1
- remark-gfm: ^4.0.0
- remark-html: ^16.0.1
- remark-prism: ^1.3.6
- sharp: ^0.33.3
- @babel/core: ^7.15.0
- @chromatic-com/storybook: ^1.2.25
- @mdx-js/loader: ^3.0.1
- @storybook/addon-actions: ^8.0.4
- @storybook/addon-essentials: ^8.0.4
- @storybook/addon-interactions: ^8.0.4
- @storybook/addon-links: ^8.0.4
- @storybook/addon-onboarding: ^8.0.4
- @storybook/blocks: ^8.0.4
- @storybook/cli: ^8.0.4
- @storybook/nextjs: ^8.0.4
- @storybook/react: ^8.0.4
- @storybook/test: ^8.0.4
- autoprefixer: ^10.4.19
- babel-loader: ^8.2.2
- eslint: ^8.57.0
- eslint-config-next: 14.1.4
- eslint-plugin-storybook: ^0.8.0
- globby: ^14.0.1
- postcss: ^8.4.38
- prettier: ^3.2.5
- rss: ^1.2.2
- storybook: ^8.0.4
- tailwindcss: ^3.4.1
Blog posts are stored in the /_posts
directory as Markdown files. Each post must include the appropriate front matter.
To create the blog posts we use remark
and remark-html
to convert the Markdown files into an HTML string, and then send it down as a prop to the page. The metadata of every post is handled by gray-matter
and also sent in props to the page.
An example of the required front matter:
Note: The formatting of the front matter is important. Ensure the indentation, and quotes remain the same.
---
title: 'A blog starter you actually want to use'
excerpt: 'There are hundreds of different blog starters out there. But none felt quite right. So I built my own. Based off the basic Next.js Blog Starter, but now with several handy features like dark mode (using local storage) or Google Analytics. It comes with Storybook too.'
coverImage: '/assets/blog/a-nextjs-blog-starter-you-actually-want-to-use/tree-minimal.jpg'
date: '2021-08-24T05:35:07.322Z'
author:
name: sandypockets
picture: '/assets/blog/authors/sandypockets_avatar.jpg'
ogImage:
url: '/assets/blog/a-nextjs-blog-starter-you-actually-want-to-use/tree-minimal.jpg'
---
Adjust the value of each key as needed.
There are two ways to create a new article: manually, or using the included script to scaffold one out.
First, you should replace the placeholder sandypockets
information in the scripts/generate-post.js
script with your own info. Then, it's as simple as running the script:
npm run new your-post-title
The script will generate a new post in the /_posts
directory with the title used in the command above, and a default front matter.
- Add a new Markdown file (
.md
) to the/_posts
directory. - Add the required front matter (described above) and adjust it as needed.
- Images related to the post should be stored in within the appropriate the
/public/assets/blog
directory. It is recommended you create a new folder for each blog post to prevent the images files from growing unwieldy. - That's it. Your new post will show up alongside the others on your homepage.
Note: The slug is the path that will be displayed, and is based on the title of your
.md
file. For example,kobe.md
becomeslocalhost:3000/posts/kobe
Contributions are what make the open source community such an amazing place to be, learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the Project
- Create your Feature or Fix Branch (
git checkout -b feature/AmazingFeature
orgit checkout -b fix/ContactForm
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Want more themes for your syntax highlighting? Check out Customize code syntax highlighting.