Installing Tailwind CSS and Related ESLint and Prettier Settings - Modern Next.js Blog Series #09

Published on
This English version was translated from my Chinese original with AI assistance.

This article is also published at it 邦幫忙 2022 iThome Ironman Contest

TL;DR

This is the 9th article in the "Modern Blog 30 Days" series. In the previous article, we enabled MDX support in Contentlayer. In this article, we will install Tailwind CSS, a CSS utility tool, and set up the corresponding ESLint and Prettier rules, getting ready to beautify our site!

Screenshot of the results:

Index Page result of Tailwind CSS

The code changes for this article are as follows:

https://github.com/eason-dev/nextjs-tailwind-contentlayer-blog-starter/compare/day08-mdx-support...day09-install-tailwindcss


Installing Tailwind CSS

pnpm add -D tailwindcss autoprefixer postcss npx tailwindcss init -p

Tweak /tailwind.config.js:

/** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [], };

Tweak /postcss.config.js:

module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, };

Modify /src/styles/globals.css by deleting all its content and replacing it with these three lines:

@tailwind base; @tailwind components; @tailwind utilities;

Applying Basic Styles to the Homepage to Try Out Tailwind CSS

Remove /src/styles/Home.module.css.

Modify /src/pages/index.tsx as follows:

import type { NextPage } from "next"; import Head from "next/head"; import { allPostsNewToOld, Post } from "@/lib/contentLayerAdapter"; export function getStaticProps() { const posts = allPostsNewToOld; return { props: { posts } }; } type Props = { posts: Post[]; }; const Home: NextPage<Props> = ({ posts }) => { return ( <div> <Head> <title>My blog</title> <meta name="description" content="Welcome to my blog" /> <link rel="icon" href="/favicon.ico" /> </Head> <main className="p-4"> <h1 className="mb-6 text-4xl font-bold">Welcome to my blog!</h1> <div className="grid grid-cols-1 gap-6 md:grid-cols-2"> {posts.map((post) => ( <div key={post.slug} className="rounded-lg border border-black p-6"> <a href={post.path}> <h2 className="mb-4 text-2xl font-semibold">{post.title}</h2> <p>{post.description}</p> </a> </div> ))} </div> </main> </div> ); }; export default Home;

Modify /src/pages/[slug].tsx as follows:

import { format, parseISO } from "date-fns"; import type { GetStaticPaths, GetStaticProps, NextPage } from "next"; import Head from "next/head"; import { useMDXComponent } from "next-contentlayer/hooks"; import { allPosts, Post } from "@/lib/contentLayerAdapter"; export const getStaticPaths: GetStaticPaths = () => { const paths = allPosts.map((post) => post.path); return { paths, fallback: false, }; }; export const getStaticProps: GetStaticProps<Props> = ({ params }) => { const post = allPosts.find((post) => post.slug === params?.slug); if (!post) { return { notFound: true, }; } return { props: { post, }, }; }; type Props = { post: Post; }; const PostPage: NextPage<Props> = ({ post }) => { const MDXContent = useMDXComponent(post.body.code); return ( <div> <Head> <title>{post.title}</title> <meta name="description" content={post.description} /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h1>{post.title}</h1> <time dateTime={post.date}> {format(parseISO(post.date), "LLLL d, yyyy")} </time> <MDXContent /> </main> </div> ); }; export default PostPage;
pnpm add -D eslint-plugin-tailwindcss prettier-plugin-tailwindcss

Modify .prettierrc.js to add the prettier-plugin-tailwindcss plugin. The final result is as follows:

module.exports = { trailingComma: "es5", singleQuote: true, printWidth: 80, semi: true, plugins: ["prettier-plugin-tailwindcss"], };

Modify .eslintrc.js:

module.exports = { extends: [ "eason", "next/core-web-vitals", "plugin:tailwindcss/recommended", "plugin:prettier/recommended", // Make this the last element so prettier config overrides other formatting rules ], plugins: ["tailwindcss"], rules: { "jsx-a11y/anchor-is-valid": [ "error", { components: ["Link"], specialLink: ["hrefLeft", "hrefRight"], aspects: ["invalidHref", "preferButton"], }, ], "tailwindcss/classnames-order": "off", // Respect prettier-plugin-tailwindcss order }, settings: { // Support absolute imports // https://www.npmjs.com/package/eslint-import-resolver-alias "import/resolver": { alias: { map: [["@", "./src"]], extensions: [".js", ".jsx", ".ts", ".tsx"], }, }, "import/ignore": ["contentLayerAdapter.js"], }, overrides: [ { files: "**/*.{ts,tsx}", extends: [ "eason/typescript", "plugin:prettier/recommended", // Make this the last element so prettier config overrides other formatting rules ], }, ], };

Results

Done! Run pnpm dev and enter the homepage, and you will see the homepage style has changed. All of it is achieved with Tailwind CSS utility classes!

The results are as follows:

Index Page result of Tailwind CSS

The code changes for this article are as follows:

https://github.com/eason-dev/nextjs-tailwind-contentlayer-blog-starter/compare/day08-mdx-support...day09-install-tailwindcss

References

https://tailwindcss.com/docs/guides/nextjs

Next Article

Congratulations! We have successfully installed Tailwind CSS and the corresponding ESLint and Prettier rules in our Next.js project, and given it a quick try.

In the next article, we will add an essential element of a modern blog: dark mode! It is also implemented with Tailwind CSS.

After that, we will start truly beautifying the styles of the entire site!