* fix(format): format the codes
* fix(format): format the code
* feat: add rehype-katex-notranslate plugin to prevent symbol in formulas to be translated.
* update(dep): update `rehype-katex-notranslate` version
This commit addresses the issue where an error was logged in the console when the user switched between light and dark modes. The warning was caused by the inappropriate use of SVG tags in JSX. The solution involved correcting the SVG tag usage to comply with JSX syntax requirements.
Closes#974
Recently, I started working on a hobby project of mine whose purpose is to help & support upcoming artists and I decided to use the Tailwind Nextjs Starter Blog, which was the perfect fit for my case: finding something that is easy to modify, use and deploy.
As it seems like on the site, I modified a lot on the "core" of Tailwind Nextjs Starter Blog and I also separated two blog parts: the actual blogging feature for my site and the lyrics part: they also generate their own sitemap, tags and RSS files, and the greatest part of it that it was really easy to add, because nowadays, sadly, I don't really have the time to work on a personal project. This is why I'd like to recommend Tailwind Nextjs Starter Blog to everyone. 👍
Hey 👋 !
Full disclosure, I work for Klaviyo! With that said, I am using this template for my own website and thought I would contribute to the repo if you don't mind!
When parsing descriptions and titles with characters like '&', '<', etc. feed was broken. This regex swaps these characters with their HTML entity equivalent.
* Add pagination support
* Change posts per page value to 10
* Change /blog/1 page to be same as /blog/
Modify canonical url to reflect current page
* Conditionally render pagination component
- [homing.so](https://homing.so) - Homing's personal blog about the stuff he's learning ([source code](https://github.com/hominsu/blog))
- [homing.so](https://homing.so) - Homing's personal blog about the stuff he's learning ([source code](https://github.com/hominsu/blog))
- [zS1m's Blog](https://contrails.space) - zS1m's personal blog for recording and sharing daily learning technical content ([source code](https://github.com/zS1m/nextjs-contrails))
- [zS1m's Blog](https://contrails.space) - zS1m's personal blog for recording and sharing daily learning technical content ([source code](https://github.com/zS1m/nextjs-contrails))
- [dariuszwozniak.net](https://dariuszwozniak.net/) - Software development blog
- [dariuszwozniak.net](https://dariuszwozniak.net/) - Software development blog ([source code](https://github.com/dariusz-wozniak/dariuszwozniak.net-v2))
- [Terminals.run](https://terminals.run) - Blog site for some thoughts and records for life and technology.
- [dreams.plus](https://dreams.plus) - Blog site for some thoughts and records for life and technology.
- [francisaguilar.co blog](https://francisaguilar.co) - Francis Aguilar's personal blog that talks about tech, fitness, and personal development.
- [francisaguilar.co blog](https://francisaguilar.co) - Francis Aguilar's personal blog that talks about tech, fitness, and personal development.
- [Min71 Dev Blog](https://min71.dev) - Personal blog about Blockchain, Development and etc. ([source code](https://github.com/mingi3442/blog))
- [Min71 Dev Blog](https://min71.dev) - Personal blog about Blockchain, Development and etc. ([source code](https://github.com/mingi3442/blog))
- [Bryce Yu's Blog](https://earayu.github.io/) - Bryce Yu's personal Blog about distributed system, database, and web development. ([source code](https://github.com/earayu/earayu.github.io))
- [Bryce Yu's Blog](https://earayu.github.io/) - Bryce Yu's personal Blog about distributed system, database, and web development. ([source code](https://github.com/earayu/earayu.github.io))
@@ -70,6 +70,9 @@ Internationalization support - [Template with i18n](https://tailwind-nextjs-star
- [LyricsDecode.com](https://lyricsdecode.com) - A song lyrics website offering original lyrics, Romanisation, and English translations with customisable viewing options.
- [LyricsDecode.com](https://lyricsdecode.com) - A song lyrics website offering original lyrics, Romanisation, and English translations with customisable viewing options.
- [bmacharia.com](https://bmacharia.com/) - Benson Macharia's technical blog about Cybersecurity and IT Risk Management.
- [bmacharia.com](https://bmacharia.com/) - Benson Macharia's technical blog about Cybersecurity and IT Risk Management.
- [armujahid.me](https://armujahid.me/) - Abdul Rauf's personal blog about tech and random stuff.
- [armujahid.me](https://armujahid.me/) - Abdul Rauf's personal blog about tech and random stuff.
- [leohuynh.dev](leohuynh.dev) - 🇻🇳 Leo's dev blog – stories, insights, and ideas. Add `/snippets`, `/books` pages, add `ProfileCard`, `CareerTimeline` components and many more.
- [OpenSats Blog](https://opensats.org/blog) - A 501(c)(3) public charity which aims to sustainably fund free and open-source projects. ([source code](https://github.com/OpenSats/website))
- [Schedles Blog](https://schedles.com/blog) - Social media scheduling tips, strategies, and product updates for content creators. ([Project Link](https://schedles.com))
Using the template? Feel free to create a PR and add your blog to this list.
Using the template? Feel free to create a PR and add your blog to this list.
@@ -82,7 +85,6 @@ Thanks to the community of users and contributors to the template! We are no lon
- [Aloisdg's cookbook](https://tambouille.vercel.app/) - with pictures and recipes!
- [Aloisdg's cookbook](https://tambouille.vercel.app/) - with pictures and recipes!
- [GautierArcin's demo with next translate](https://tailwind-nextjs-starter-blog-seven.vercel.app/) - includes translation of mdx posts, [source code](https://github.com/GautierArcin/tailwind-nextjs-starter-blog/tree/demo/next-translate)
- [GautierArcin's demo with next translate](https://tailwind-nextjs-starter-blog-seven.vercel.app/) - includes translation of mdx posts, [source code](https://github.com/GautierArcin/tailwind-nextjs-starter-blog/tree/demo/next-translate)
- [David Levai's digital garden](https://davidlevai.com/) - customized design and added email subscriptions
- [David Levai's digital garden](https://davidlevai.com/) - customized design and added email subscriptions
- [Leo's Blog](https://leohuynh.dev) - Tuan Anh Huynh's personal site. Add Snippets Page, Author Profile Card, Image Lightbox, ...
- [thvu.dev](https://thvu.dev) - Added `mdx-embed`, view count, reading minutes and more.
- [thvu.dev](https://thvu.dev) - Added `mdx-embed`, view count, reading minutes and more.
- [irvin.dev](https://www.irvin.dev/) - Irvin Lin's personal site. Added YouTube embedding.
- [irvin.dev](https://www.irvin.dev/) - Irvin Lin's personal site. Added YouTube embedding.
- [KirillSo.com](https://www.kirillso.com/) - Personal blog & website.
- [KirillSo.com](https://www.kirillso.com/) - Personal blog & website.
@@ -318,8 +320,8 @@ Consider removing the following features that cannot be used in a static build:
## Frequently Asked Questions
## Frequently Asked Questions
- [How can I add a custom MDX component?](/faq/custom-mdx-component.md)
- [How can I add a custom MDX component?](faq/custom-mdx-component.md)
- [How can I customize the `kbar` search?](/faq/customize-kbar-search.md)
- [How can I customize the `kbar` search?](faq/customize-kbar-search.md)
summary: 'Markdown cheatsheet for all your blogging needs - headers, lists, images, tables and more! An illustrated guide based on GitHub Flavored Markdown.'
---
# Introduction
Markdown and Mdx parsing is supported via `unified`, and other remark and rehype packages. `next-mdx-remote` allows us to parse `.mdx` and `.md` files in a more flexible manner without touching webpack.
GitHub flavored markdown is used. `mdx-prism` provides syntax highlighting capabilities for code blocks. Here's a demo of how everything looks.
The following markdown cheatsheet is adapted from: https://guides.github.com/features/mastering-markdown/
# What is Markdown?
Markdown is a way to style text on the web. You control the display of the document; formatting words as bold or italic, adding images, and creating lists are just a few of the things we can do with Markdown. Mostly, Markdown is just regular text with a few non-alphabetic characters thrown in, like `#` or `*`.
# Syntax guide
Here’s an overview of Markdown syntax that you can use anywhere on GitHub.com or in your own text files.
Here’s an example of how you can use syntax highlighting with [GitHub Flavored Markdown](https://help.github.com/articles/basic-writing-and-formatting-syntax/):
````
```js:fancyAlert.js
function fancyAlert(arg) {
if (arg) {
$.facebox({ div: '#foo' })
}
}
```
````
And here's how it looks - nicely colored with styled code titles!
```js:fancyAlert.js
function fancyAlert(arg) {
if (arg) {
$.facebox({ div: '#foo' })
}
}
```
## Footnotes
```
Here is a simple footnote[^1]. With some additional text after it.
[^1]: My reference.
```
Here is a simple footnote[^1]. With some additional text after it.
[^1]: My reference.
## Task Lists
```
- [x] list syntax required (any unordered or ordered list supported)
- [x] this is a complete item
- [ ] this is an incomplete item
```
- [x] list syntax required (any unordered or ordered list supported)
- [x] this is a complete item
- [ ] this is an incomplete item
## Tables
You can create tables by assembling a list of words and dividing them with hyphens `-` (for the first row), and then separating each column with a pipe `|`:
summary: 'In this article we introduce adding images in the tailwind starter blog and the benefits and limitations of the next/image component.'
authors: ['default']
---
# Introduction
The tailwind starter blog has out of the box support for [Next.js's built-in image component](https://nextjs.org/docs/api-reference/next/image) and automatically swaps out default image tags in markdown or mdx documents to use the Image component provided.
# Usage
To use in a new page route / javascript file, simply import the image component and call it e.g.
```js
import Image from 'next/image'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image src="/me.png" alt="Picture of the author" width={500} height={500} />
<p>Welcome to my homepage!</p>
</>
)
}
export default Home
```
For a markdown file, the default image tag can be used and the default `img` tag gets replaced by the `Image` component in the build process.
Assuming we have a file called `ocean.jpg` in `static/images/ocean.jpg`, the following line of code would generate the optimized image.
```

```
Alternatively, since we are using mdx, we can just use the image component directly! Note, that you would have to provide a fixed width and height. The `img` tag method parses the dimension automatically.
- Optimization on demand instead of build-time - no increase in build time!
# Limitations
- Due to the reliance on `next/image`, unless you are using an external image CDN like Cloudinary or Imgix, it is practically required to use Vercel for hosting. This is because the component acts like a serverless function that calls a highly optimized image CDN.
If you do not want to be tied to Vercel, you can remove `imgToJsx` in `remarkPlugins` in `lib/mdx.js`. This would avoid substituting the default `img` tag.
Alternatively, one could wait for image optimization at build time to be supported. A different library, [next-optimized-images](https://github.com/cyrilwanner/next-optimized-images) does that, although it requires transforming the images through webpack which is not done here.
- Images from external links are not passed through `next/image`
- All images have to be stored in the `public` folder e.g `/static/images/ocean.jpeg`
> #### Now that I think about it, they kind of took advantage of me
### Side work for Aunt Laurie
The first piece of hardware I ever owned was given to me by my dear Aunt. At the time she had worked for a company that sold industrial saw blades and she was frequently fixing their IT issues despite being an accountant. To this day it still infuriates me how much they took advantage of her. Now that I think about it, they kind of took advantage of me. You see I had worked for GeekSquad at the time and looking back at it, I realize how little I knew then. While I know there is always more to learn in the industry, what you learn pretty quickly is that your time is valuable, and that not everyone views IT work as "easy" and "no big deal". If they had invited an IT consultant to do the 3 hours of work I did, the bill easily would have been hundreds of dollars. These days, I don't charge by the hour, I charge by the job. This way, I can work quickly and not get penalized for it.
She asked me in to help take a look at a virus infecting some of the computers at the office. This virus was mean; one of those that would keep creating itself until you found the source process. I don't really think it was a self-replicating-worm-type-of-virus because it didn't spread to all of the computers in the network, just a few. It was more like one of those click-a-link-in-an-email-that-you-shouldn't-have types. No, Harbor freights doesn't have a free gift card for you. What is free, is the headache it takes to find the dang source. I was able to find it only because i suggested an antivirus I liked: Webroot. It was one of the most performant and reliable anti-viruses I have ever seen. After convincing my aunt to buy it, I whipped up a batch file to install the application and register it all in one go. Boyyyy now that I think about it, that's probably when I really started to enjoy writing code/scripting. After using the script, Webroot immediately found the source process and resource usage went back to normal.
"Would you like a computer?"
"A what?" I respond confused (I was expecting money). She starts walking to the networking closet where I see an old dell tower sitting on the floor. At first I think it's just a desktop, but after looking at the label closely, I realize it's actually a server in desktop form. She was offering me a Dell T100 equipped with a quad core Xeon processor(Intel Server CPU) and 4 bays for hard drives. Hard drives included.
"Oh Sweet! Thanks Auntie Lar!"
Despite not being paid like a professional, this was sufficient compensation. While it wasn't the most powerful server on the market, it definitely would do anything I ask it. This leaves just one question...
### A way to watch movies
> What should I ask it to do?
The computer sits in my room for months. Every glance in its direction, I ask my self: "What should I ask it to do?". A month or two later, I am lounging in the living room with my parents watching OTA tv. My father just did a scan of channels and while we are flipping through the channels we come across The Fresh Prince of Bel-Air reruns. We couldn't get enough. I was so happy. You see, you couldn't find those reruns on OTA in San Antonio; And we just happened to be getting a channel from Austin! This goes on for a couple of days then one day, the floor just gets pull from underneath our feet. We were no longer getting signal! I have my answer to the question now. I am going to download The Fresh Prince of Bel-Air and watch it off my server. After installing Windows Sever 2012 Edition, I install plex. I happily download The Fresh Prince of Bel-Air and ironically, to this day I haven't watched all the episodes. I still have all of the files though.
### Learning virtualization
"So what do you like to do with your free time?"
"I love watching movies! I have a plex server. I also like to play Video Games like League of legends and Overwatch." I smile as I respond to my future Manager.
"That's cool, I have one too. Well alright, we are going to give you a technical interview now. Here's the packet. You have an hour."
I would say the interview went well. After all, I got the job. This was my first "Corporate Job". The exposure really required me to teach my self on the side. Using VMWare ESXI was very easy. Their bare metal hypervisor came with networking, storage management etc and was reasonably intuitive.
Downloading and setting up linux virtual machines with each application was challenging yet rewarding. Setting up servers manually and then installing the applications was an involved process; One that likely set the ground work for understanding the use case of containers. Being RHEL certified did afford me a large degree of appreciation for linux. I would combine these later to make managing my home lab much, much easier. But, hey, you live and you learn. In this case I learned that I was demanding too much of my little Dell T100 server. I would need to build it bigger. After all, I was already at home.
### Building from scratch
Ebay, is a great website. You can find anything from car parts to an ice tea maker. They also sell things from China. Did you know you could buy server parts from Ebay? I built a dual processor server. Guess how much each processor was? $5. And the RAM(Memory)? $7. Just to put that in perspective, *new* processors were *hundreds* of dollars, sometimes even thousands. Ebay enabled me build an affordable home lab server. It was great while it lasted.....
### 15 amp circuit breaker
Did you know, in America, there are two typical types of circuits run in residential rooms? Me either! For example, your bedroom likely has several outlets however in most cases they all are sharing the same power connection or circuit. These circuits have a maximum amount of power they can safely pull before the safety switch or circuit breaker will "trip". I learned this the hard way. You see, I lived my grandparents at the time and my grandfather needed the house warmer to stay healthy and in a good mood. So my grandmother and I never raised the temperature. But since we live in Texas, I needed something to cool down my room. I was in the middle of an Overwatch gaming session and all of the sudden the pc shuts off. I new instantly the circuit breaker tripped because the AC shutoff too. I ran over to the circuit panel, slapped the breaker on and ran right back to my game. Booted the PC and get back in game as quickly as possible. Trips again. Turn it back on. I repeat this business another time before I give up. A gaming PC, a couple of servers and an air conditioner draw a lot of power. When all three are running on the same circuit, it can cause it to trip. I find out later the circuit in my room is a 15 amp breaker, instead of a 20! At least I know now. I go to watch a movie on Plex and I notice plex isn't loading. I walk over to the servers and power them on. The Dell T100 works just fine. My custom server, won't turn on! Panic sets in.
summary: 'Looking for a performant, out of the box template, with all the best in web technology to support your blogging needs? Checkout the Tailwind Nextjs Starter Blog template.'
[](https://vercel.com/new/git/external?repository-url=https://github.com/timlrx/tailwind-nextjs-starter-blog)
> [!CAUTION]
> This is the README of version 1 of the template. It is kept for historical reasons, but is no longer supported. It also serves as a nice example of [Github Alert](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts). For the actual documentation, please refer to the [Github repository](https://github.com/timlrx/tailwind-nextjs-starter-blog).
This is a [Next.js](https://nextjs.org/), [Tailwind CSS](https://tailwindcss.com/) blogging starter template. Probably the most feature-rich Next.js markdown blogging template out there. Comes out of the box configured with the latest technologies to make technical writing a breeze. Easily configurable and customizable. Perfect as a replacement to existing Jekyll and Hugo individual blogs.
Check out the documentation below to get started.
Facing issues? Check the [FAQ page](https://github.com/timlrx/tailwind-nextjs-starter-blog/wiki) and do a search on past issues. Feel free to open a new issue if none has been posted previously.
Feature request? Check the past discussions to see if it has been brought up previously. Otherwise, feel free to start a new discussion thread. All ideas are welcomed!
## Examples
- [Demo Blog](https://tailwind-nextjs-starter-blog.vercel.app/) - this repo
- [My personal blog](https://www.timlrx.com) - modified to auto-generate blog posts with dates
- [Aloisdg's cookbook](https://tambouille.vercel.app/) - with pictures and recipes!
- [GautierArcin's demo with next translate](https://tailwind-nextjs-starter-blog-seven.vercel.app/) - includes translation of mdx posts, [source code](https://github.com/GautierArcin/tailwind-nextjs-starter-blog/tree/demo/next-translate)
- [David Levai's digital garden](https://davidlevai.com/) - customized design and added email subscriptions
- [Thinh's Corner](https://thinhcorner.com/) - [customized layout](https://github.com/Th1nhNg0/th1nhng0.vercel.app/blob/5e73a420828d82f01e7147512a2c3273c4ec19f8/layouts/PostLayout.js) with sticky side table of contents
Using the template? Feel free to create a PR and add your blog to this list.
## Motivation
I wanted to port my existing blog to Nextjs and Tailwind CSS but there was no easy out of the box template to use so I decided to create one. Design is adapted from [Tailwindlabs blog](https://github.com/tailwindlabs/blog.tailwindcss.com).
I wanted it to be nearly as feature-rich as popular blogging templates like [beautiful-jekyll](https://github.com/daattali/beautiful-jekyll) and [Hugo Academic](https://github.com/wowchemy/wowchemy-hugo-modules) but with the best of React's ecosystem and current web development's best practices.
## Features
- Easy styling customization with [Tailwind 3.0](https://tailwindcss.com/blog/tailwindcss-v3) and primary color attribute
- Near perfect lighthouse score - [Lighthouse report](https://www.webpagetest.org/result/210111_DiC1_08f3670c3430bf4a9b76fc3b927716c5/)
- Lightweight, 45kB first load JS, uses Preact in production build
- Mobile-friendly view
- Light and dark theme
- Self-hosted font with [Fontsource](https://fontsource.org/)
- Supports [plausible](https://plausible.io/), [simple analytics](https://simpleanalytics.com/) and google analytics
- [MDX - write JSX in markdown documents!](https://mdxjs.com/)
- Server-side syntax highlighting with line numbers and line highlighting via [rehype-prism-plus](https://github.com/timlrx/rehype-prism-plus)
- Math display supported via [KaTeX](https://katex.org/)
- Citation and bibliography support via [rehype-citation](https://github.com/timlrx/rehype-citation)
- Automatic image optimization via [next/image](https://nextjs.org/docs/basic-features/image-optimization)
- Flexible data retrieval with [mdx-bundler](https://github.com/kentcdodds/mdx-bundler)
- Support for tags - each unique tag will be its own page
- Support for multiple authors
- Blog templates
- TOC component
- Support for nested routing of blog posts
- Newsletter component with support for Mailchimp, Buttondown, Convertkit, Klaviyo, Revue, Emailoctopus and Beehiiv
- Supports [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus
2. Personalize `siteMetadata.js` (site related information)
3. Modify the content security policy in `next.config.js` if you want to use
any analytics provider or a commenting solution other than giscus.
4. Personalize `authors/default.md` (main author)
5. Modify `projectsData.ts`
6. Modify `headerNavLinks.ts` to customize navigation links
7. Add blog posts
8. Deploy on Vercel
## Development
First, run the development server:
```bash
npm start
# or
npm run dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
## Extend / Customize
`data/siteMetadata.js` - contains most of the site related information which should be modified for a user's need.
`data/authors/default.md` - default author information (required). Additional authors can be added as files in `data/authors`.
`data/projectsData.js` - data used to generate styled card on the projects page.
`data/headerNavLinks.js` - navigation links.
`data/logo.svg` - replace with your own logo.
`data/blog` - replace with your own blog posts.
`public/static` - store assets such as images and favicons.
`tailwind.config.js` and `css/tailwind.css` - contain the tailwind stylesheet which can be modified to change the overall look and feel of the site.
`css/prism.css` - controls the styles associated with the code blocks. Feel free to customize it and use your preferred prismjs theme e.g. [prism themes](https://github.com/PrismJS/prism-themes).
`components/social-icons` - to add other icons, simply copy an svg file from [Simple Icons](https://simpleicons.org/) and map them in `index.js`. Other icons use [heroicons](https://heroicons.com/).
`components/MDXComponents.js` - pass your own JSX code or React component by specifying it over here. You can then call them directly in the `.mdx` or `.md` file. By default, a custom link and image component is passed.
`layouts` - main templates used in pages.
`pages` - pages to route to. Read the [Next.js documentation](https://nextjs.org/docs) for more information.
`next.config.js` - configuration related to Next.js. You need to adapt the Content Security Policy if you want to load scripts, images etc. from other domains.
images (optional, if none provided defaults to socialBanner in siteMetadata config)
authors (optional list which should correspond to the file names in `data/authors`. Uses `default` if none is specified)
layout (optional list which should correspond to the file names in `data/layouts`)
canonicalUrl (optional, canonical url for the post for SEO)
```
Here's an example of a post's frontmatter:
```
---
title: 'Introducing Tailwind Nexjs Starter Blog'
date: '2021-01-12'
lastmod: '2021-01-18'
tags: ['next-js', 'tailwind', 'guide','yoyoyoy']
draft: false
summary: 'Looking for a performant, out of the box template, with all the best in web technology to support your blogging needs? Checkout the Tailwind Nextjs Starter Blog template.'
Run `node ./scripts/compose.js` to bootstrap a new post.
Follow the interactive prompt to generate a post with pre-filled front matter.
## Deploy
**Vercel**
The easiest way to deploy the template is to use the [Vercel Platform](https://vercel.com) from the creators of Next.js. Check out the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
**Netlify / GitHub Pages / Firebase etc.**
As the template uses `next/image` for image optimization, additional configurations have to be made to deploy on other popular static hosting websites like [Netlify](https://www.netlify.com/) or [GitHub Pages](https://pages.github.com/). An alternative image optimization provider such as Imgix, Cloudinary or Akamai has to be used. Alternatively, replace the `next/image` component with a standard `<img>` tag. See [`next/image` documentation](https://nextjs.org/docs/basic-features/image-optimization) for more details.
The API routes used in the newsletter component cannot be used in a static site export. You will need to use a form API endpoint provider and substitute the route in the newsletter component accordingly. Other hosting platforms such as Netlify also offer alternative solutions - please refer to their docs for more information.
## Support
Using the template? Support this effort by giving a star on GitHub, sharing your own blog and giving a shoutout on Twitter or be a project [sponsor](https://github.com/sponsors/timlrx).
title: 'Release of Tailwind Nextjs Starter Blog v2.0'
date: '2023-08-05'
lastmod: '2023-08-05'
tags: ['next-js', 'tailwind', 'guide', 'feature']
draft: true
summary: 'Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.'
images: ['/static/images/twitter-card.png']
---
## Introduction
Welcome to the release of Tailwind Nextjs Starter Blog template v2.0. This release is a major refactor of the codebase to support Nextjs App directory and React Server Components. Read on to discover the new features and how to migrate from V1.
The template was first released in January 2021 and has since been used by thousands of users. It is featured on [Next.js Templates](https://vercel.com/templates/next.js/tailwind-css-starter-blog), [Tailwind Awesome](https://www.tailwindawesome.com/resources/tailwind-nextjs-starter-blog) among other listing sites. It attracts 200+ unique visitors daily notching 1500-2000 page views, with 1.3k forks and many other clones.
Many thanks to the community of users and contributors for making this template a success! I created a small video montage of the blogs (while cleaning up the list in the readme) to showcase the diversity of the blogs created using the template and to celebrate the milestone:
Version 2 builds on the success of the previous version and introduces many new features and improvements. The codebase has been refactored to support Next.js App directory and React Server Components. Markdown / MDX is now processed using Contentlayer, a type-safe content SDK that validates and transforms your content into type-safe JSON data. It integrates with Pliny, a new library that provides out of the box Next.js components to enhance your static site with analytics, comments and newsletter subscription. A new command palette (⌘-k) search component is also added to the template.
Let's dive into the new features and improvements in V2.
## Next.js App Directory and React Server Components
Now that [Next.js App router](https://nextjs.org/docs/app) is finally stable and is mostly feature compatible with Page Router, the codebase has been migrated to new setup. This allows for a hybrid rendering approach, with the use of React Server Components generated on the server side for faster page loads and smaller bundle sizes, while retaining the ability to sprinkle in client side React components for interactivity.[^1]
With addition powers comes a [new paradigm](https://nextjs.org/docs/getting-started/react-essentials) to learn. I have migrated the codebase to make use of the new features as much as possible. This includes changes in the folder structure, splitting components into server vs client components, leveraging server side data fetching and using the recommended [Metadata](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) API for SEO discoverability.
While this simplifies the codebase to some extent, it makes migration from the old codebase more difficult. If you are looking to migrate, I recommend starting from a fresh template and copying over your customizations and existing content. See the [migration recommendations](#migration-recommendations) section for more details.
## Typescript First
The codebase has been migrated to Typescript. While the previous version of the template was available in both Javascript and Typescript, I decided to reduce the maintenance burden and focus on Typescript. This also allows for better type checking and code completion in IDEs.
Typescript is also a perfect match with our new type-safe markdown processor - Contentlayer.
## Contentlayer
[Contentlayer](https://www.contentlayer.dev/) is a content SDK that validates and transforms your content into type-safe JSON data that you can easily import into your application. It makes working with local markdown or MDX files a breeze. This replaces `MDX-bundler` and our own markdown processing workflow.
First, a content source is defined, specifying the name of the document type, the source where it is located along with the frontmatter fields and any additional computed fields that should be generated as part of the process.
Contentlayer then processes the MDX files with our desired markdown remark or rehype plugins, validates the schema, generate type definitions and output json files that can be easily imported in our pages. Hot reloading comes out of the box, so edits to the markdown files will be reflected in the browser immediately!
## Pliny
A large reason for the popularity of the template was its customizability and integration with other services from analytics providers to commenting solutions. However, this means that a lot of boilerplate code has to be co-located within the template even if the user does not use the feature. Updates and bug fixes had to be copied manually to the user's codebase.
To solve this, I have abstracted the logic to a separate repository - [Pliny](https://github.com/timlrx/pliny). Pliny provides out of the box Next.js components to enhance static sites:
- Analytics
- Google Analytics
- Plausible Analytics
- Simple Analytics
- Umami Analytics
- Posthog
- Comments
- Disqus
- Giscus
- Utterances
- Newsletter (uses Next 13 API Routes)
- Buttondown
- Convertkit
- Email Octopus
- Klaviyo
- Mailchimp
- Revue
- Command palette search with tailwind style sheet
- Algolia
- Kbar (local search)
- UI utility components
- Bleed
- Newsletter / Blog Newsletter
- Pre / Code block
- Table of Contents
Choose your preferred service by modifying `siteMetadata.js` and changing the appropriate fields. For example to change from Umami Analytics to Plausible, we can change the following fields:
```diff-js:siteMetadata.js
analytics: {
- umamiAnalytics: {
- // We use an env variable for this site to avoid other users cloning our analytics ID
- umamiWebsiteId: process.env.NEXT_UMAMI_ID, // e.g. 123e4567-e89b-12d3-a456-426614174000
- },
+ plausibleAnalytics: {
+ plausibleDataDomain: '', // e.g. tailwind-nextjs-starter-blog.vercel.app
+ },
},
```
Changes in the configuration file gets propagated to the components automatically. No modification to the template is required.
Under the hood, Pliny exports high level components such as `<Analytics analyticsConfig={analyticsConfig}/>` and `<Comments commentsConfig={commentsConfig}/>` which takes in a configuration object and renders the appropriate component. Since the layouts are defined on the server side, Next.js is able to use the configuration object to determine which component to render and send only the required component bundle to the client.
## New Search Component
What's a blog in 2023 without a command palette search bar?
One of the most highly requested features have been added 🎉! The search component supports 2 search providers - Algolia and Kbar local search.
### Algolia
[Algolia Docsearch](https://docsearch.algolia.com/) is popular free service used across many documentation websites. It automatically scrapes the website that has is submitted for indexing and makes the search result available via a beautiful dialog modal. The pliny component is greatly inspired by the Docusaurus implementation and comes with a stylesheet that is compatible with the Tailwind CSS theme.
### Kbar
[Kbar](https://github.com/timc1/kbar) is a fast, portable, and extensible cmd+k interface. The pliny implementation uses kbar to create a local search dialog box. The component loads a JSON file, default `search.json`, that was created in the contentlayer build process. Try pressing ⌘-k or ctrl-k to see the search bar in action!
## Styling and Layout Updates
### Theming
`tailwind.config.js` has been updated to use tailwind typography defaults where possible and to use the built-in support for dark mode via the `prose-invert` class. This replaces the previous `prose-dark` class and configuration.
The primary theme color is updated from `teal` to `pink` and the primary gray theme from `neutral` to `gray`.
Inter is now replaced with Space Grotesk as the default font.
### New Layouts
Layout components available in the `layouts` directory, provide a simple way to customize the look and feel of the blog.[^2]
The downside of building a popular template is that you start seeing multiple similar sites everywhere 😆. While users are encouraged to customized the layouts to their liking, having more layout options that are easily switchable promotes diversity and perhaps can be a good starting point for further customizations.
In v2, I added a new post layout - `PostBanner`. It features a large banner image and a centered content container. Check out "[Pictures of Canada](/blog/pictures-of-canada)" blog post which has been updated to use the new layout.
The default blog listing layout has also been updated to include a side bar with blog tags. The search bar in the previous layout has been replace with the new command palette search. To switch back to the old layout, simply change the pages that use the `ListLayoutWithTags` component back to the original `ListLayout`.
## Migration Recommendations
Due to the large changes in directory structure, setup and tooling, I recommend starting from a fresh template and copying existing content, followed by incrementally migrating changes over to the new template.
Styling changes should be relatively minor and can be copied over from the old `tailwind.config.js` to the new one. If copying over, you might need to add back the `prose-dark` class to components that opt into tailwind typography styling. Do modify the font import in the root layout component to use the desired font of choice.
Changes to the MDX processing pipeline and schema can be easily ported to the new Contentlayer setup. If there are changes to the frontmatter fields, you can modify the document type in `contentlayer.config.ts` to include the new fields. Custom plugins can be added to the `remarkPlugins` and `rehypePlugins` properties in the `makeSource` export of `contentlayer.config.ts`.
Markdown layouts are no longer sourced automatically from the `layouts` directory. Instead, they have to be specified in the `layouts` object defined in `blog/[...slug]/page.tsx`.[^3]
To port over larger components or pages, I recommend first specificing it as a client component by using the `"use client"` directive. Once it renders correctly, you can split the interactive components (parts that rely on `use` hooks) as a client component and keep the remaining code as a server component. Consult the comprehensive Next.js [migration guide](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#migrating-from-pages-to-app) for more details.
## Conclusion
I hope you enjoy the new features and improvements in V2. If you have any feedback or suggestions, feel free to open an issue or reach out to me on [Twitter](https://twitter.com/timlrx).
## Support
Using the template? Support this effort by giving a star on GitHub, sharing your own blog and giving a shoutout on Twitter or be a project [sponsor](https://github.com/sponsors/timlrx).
[^1]: The previous version injects Preact into the production build. However, this is no longer possible as it does not support React Server Components. While overall bundle size has increased to about 85kB, most of the content can be pre-rendered on the server side, resulting in a low first contentful paint and time to interactive. Using React throughtout also leads to more consistent behavior with external libraries and components.
[^2]: This is different from Next.js App Directory layouts and are best thought of as reusable React containers.
[^3]: This takes advantage of Server Components by making it simple to specify the layout of choice in the markdown file and match against the `layouts` object which is then used to render the appropriate layout component.
Follow the [official Next.js repo docker build example and instructions](https://github.com/vercel/next.js/tree/canary/examples/with-docker) to deploy with docker. Copy the [`Dockerfile`](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile) into the root of the project and modify the `next.config.js` file:
```js
// next.config.js
module.exports={
// ... rest of the configuration.
output:'standalone',
}
```
You can now build the docker image and run it:
```bash
docker build -t nextjs-docker .
docker run -p 3000:3000 nextjs-docker
```
Alternatively, to use docker compose, refer to the [docker compose repo](https://github.com/vercel/next.js/tree/canary/examples/with-docker-compose).
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.