Introduction
Hey there, fellow UI developer! Are you ready to embark on an exciting journey to create a powerful and stylish web application? You've come to the right place! In this blog post, we're going to walk through the process of setting up a Next.js app with Tailwind CSS and TypeScript. This combination of technologies will give you a robust foundation for building modern, responsive, and type-safe web applications.
Whether you're new to these tools or looking to refresh your knowledge, this guide will provide you with all the information you need to get started. We'll cover everything from installation to configuration, and even throw in some tips and tricks along the way. So, grab your favorite beverage, fire up your code editor, and let's dive in!
Why Next.js, Tailwind CSS, and TypeScript?
Before we start coding, let's take a moment to understand why this tech stack is so popular among developers:
Next.js: The React Framework for Production
Next.js is a powerful React framework that provides a ton of built-in features to make your development process smoother. Some key benefits include:
- Server-side rendering
- Automatic code splitting
- Route pre-fetching
- Built-in CSS support
- API routes
Tailwind CSS: Utility-First CSS Framework
Tailwind CSS is a highly customizable, low-level CSS framework that gives you all the building blocks you need to create bespoke designs. Here's why developers love it:
- Rapid UI development
- Consistent design system
- Highly customizable
- Smaller bundle sizes with PurgeCSS
TypeScript: JavaScript with Superpowers
TypeScript adds static typing to JavaScript, which can help catch errors early and improve code quality. Benefits include:
- Better code documentation
- Enhanced IDE support
- Easier refactoring
- Improved team collaboration
Now that we understand the why, let's get into the how!
Setting Up Your Development Environment
Before we create our next-app with Tailwind and TypeScript, we need to make sure our development environment is properly set up.
Node.js and npm
First things first, you'll need Node.js installed on your machine. Next.js requires Node.js 12.0 or later. To check if you have Node.js installed, open your terminal and run:
node --version
If you don't have Node.js installed, or if your version is outdated, head over to the official Node.js website and download the latest stable version.
Code Editor
While you can use any text editor for coding, I highly recommend using Visual Studio Code. It's free, open-source, and has excellent support for JavaScript, TypeScript, and React development. Plus, there are numerous helpful extensions available that can boost your productivity.
Creating Your Next.js App
Now that we have our environment ready, let's create our Next.js app with Tailwind CSS and TypeScript.
Using create-next-app
The easiest way to get started with Next.js is by using create-next-app
. This CLI tool sets up a new Next.js project with a single command. Open your terminal, navigate to the directory where you want to create your project, and run:
npx create-next-app@latest my-next-app --typescript --tailwind --eslint
Let's break down this command:
-
npx
allows us to run the latest version ofcreate-next-app
without installing it globally -
my-next-app
is the name of your project (feel free to change this!) -
--typescript
flag adds TypeScript support -
--tailwind
flag adds Tailwind CSS configuration -
--eslint
flag adds ESLint for code linting
After running this command, create-next-app
will set up a new Next.js project with TypeScript and Tailwind CSS pre-configured. It might take a few minutes to install all the necessary dependencies.
Project Structure
Once the installation is complete, let's take a look at the project structure:
my-next-app/
├── node_modules/
├── pages/
│ ├── _app.tsx
│ ├── index.tsx
│ └── api/
├── public/
├── styles/
│ └── globals.css
├── .eslintrc.json
├── next-env.d.ts
├── next.config.js
├── package.json
├── postcss.config.js
├── README.md
├── tailwind.config.js
└── tsconfig.json
Let's go through some of the key files and directories:
pages/
This directory contains your application's routes. Each file in this directory becomes a route based on its name.
pages/_app.tsx
This is the main component that wraps all other pages. It's used to keep state when navigating between pages or to add global styles.
pages/index.tsx
This is your home page. It's what users will see when they visit the root of your site.
styles/globals.css
This file contains global styles and is where Tailwind's base styles are imported.
tailwind.config.js
This is where you can customize your Tailwind installation.
tsconfig.json
This file specifies the root files and the compiler options required to compile the project.
Customizing Your Next.js App
Now that we have our basic setup, let's customize it a bit to get a feel for how everything works together.
Modifying the Home Page
Open pages/index.tsx
and replace its contents with the following:
import Head from 'next/head'
export default function Home() {
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
<Head>
<title>My Next.js App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex flex-col items-center justify-center flex-1 px-20 text-center">
<h1 className="text-6xl font-bold">
Welcome to{' '}
<a className="text-blue-600" href="https://nextjs.org">
Next.js!
</a>
</h1>
<p className="mt-3 text-2xl">
Get started by editing{' '}
<code className="p-3 font-mono text-lg bg-gray-100 rounded-md">
pages/index.tsx
</code>
</p>
<div className="flex flex-wrap items-center justify-around max-w-4xl mt-6 sm:w-full">
<a
href="https://nextjs.org/docs"
className="p-6 mt-6 text-left border w-96 rounded-xl hover:text-blue-600 focus:text-blue-600"
>
<h3 className="text-2xl font-bold">Documentation →</h3>
<p className="mt-4 text-xl">
Find in-depth information about Next.js features and API.
</p>
</a>
<a
href="https://nextjs.org/learn"
className="p-6 mt-6 text-left border w-96 rounded-xl hover:text-blue-600 focus:text-blue-600"
>
<h3 className="text-2xl font-bold">Learn →</h3>
<p className="mt-4 text-xl">
Learn about Next.js in an interactive course with quizzes!
</p>
</a>
</div>
</main>
<footer className="flex items-center justify-center w-full h-24 border-t">
<a
className="flex items-center justify-center"
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<img src="/vercel.svg" alt="Vercel Logo" className="h-4 ml-2" />
</a>
</footer>
</div>
)
}
This code creates a simple landing page using Tailwind CSS classes for styling. It includes a main heading, a brief description, and two card-like links to Next.js resources.
Adding a New Page
Let's add a new page to our app. Create a new file called about.tsx
in the pages
directory and add the following content:
import Head from 'next/head'
import Link from 'next/link'
export default function About() {
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
<Head>
<title>About - My Next.js App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex flex-col items-center justify-center flex-1 px-20 text-center">
<h1 className="text-6xl font-bold">About Page</h1>
<p className="mt-3 text-2xl">
This is a simple about page to demonstrate routing in Next.js
</p>
<Link href="/">
<a className="mt-6 text-blue-600 hover:underline">Back to Home</a>
</Link>
</main>
</div>
)
}
This creates a simple "About" page and demonstrates how easy it is to add new pages in Next.js.
Working with TypeScript
One of the great things about using TypeScript with Next.js is the improved developer experience. Let's create a simple component to see TypeScript in action.
Create a new directory called components
in the root of your project, and inside it, create a file called Button.tsx
:
import React from 'react'
interface ButtonProps {
text: string
onClick: () => void
}
const Button: React.FC<ButtonProps> = ({ text, onClick }) => {
return (
<button
className="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700"
onClick={onClick}
>
{text}
</button>
)
}
export default Button
Now, let's use this button in our index.tsx
file. Update the file to include:
import Head from 'next/head'
import Button from '../components/Button'
export default function Home() {
const handleClick = () => {
alert('Button clicked!')
}
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
{/* ... (previous content) ... */}
<Button text="Click me!" onClick={handleClick} />
</div>
)
}
With TypeScript, you'll get autocompletion and type checking for your component props, making it easier to use components correctly and catch errors early.
Customizing Tailwind CSS
Tailwind CSS is highly customizable. Let's make a few changes to the default configuration to see how it works.
Open tailwind.config.js
and update it to look like this:
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
'custom-blue': '#1e40af',
'custom-green': '#15803d',
},
fontFamily: {
sans: ['Roboto', 'sans-serif'],
},
},
},
plugins: [],
}
This configuration adds two custom colors and changes the default font to Roboto.
To use the new custom colors, you can update the Button component:
const Button: React.FC<ButtonProps> = ({ text, onClick }) => {
return (
<button
className="px-4 py-2 font-bold text-white bg-custom-blue rounded hover:bg-custom-green"
onClick={onClick}
>
{text}
</button>
)
}
Remember to import the Roboto font in your _app.tsx
file:
import '../styles/globals.css'
import { AppProps } from 'next/app'
import Head from 'next/head'
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"
rel="stylesheet"
/>
</Head>
<Component {...pageProps} />
</>
)
}
export default MyApp
Adding Interactivity with React Hooks
Let's add some interactivity to our app using React hooks. We'll create a simple counter component.
Create a new file components/Counter.tsx
:
import React, { useState } from 'react'
import Button from './Button'
const Counter: React.FC = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
const decrement = () => setCount(count - 1)
return (
<div className="flex flex-col items-center mt-8">
<h2 className="text-2xl font-bold mb-4">Counter: {count}</h2>
<div className="flex space-x-4">
<Button text="Increment" onClick={increment} />
<Button text="Decrement" onClick={decrement} />
</div>
</div>
)
}
export default Counter
Now, add this Counter component to your index.tsx
:
import Head from 'next/head'
import Button from '../components/Button'
import Counter from '../components/Counter'
export default function Home() {
const handleClick = () => {
alert('Button clicked!')
}
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
{/* ... (previous content) ... */}
<Button text="Click me!" onClick={handleClick} />
<Counter />
</div>
)
}
This demonstrates how we can use React hooks (useState in this case) with TypeScript in our Next.js app.
Fetching Data
Next.js provides several methods for fetching data. Let's create a simple example using the getStaticProps
function to fetch data at build time.
Create a new file pages/users.tsx
:
import { GetStaticProps } from 'next'
import Head from 'next/head'
import Link from 'next/link'
interface User {
id: number
name: string
email: string
}
interface UsersProps {
users: User[]
}
export default function Users({ users }: UsersProps) {
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
<Head>
<title>Users - My Next.js App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex flex-col items-center justify-center flex-1 px-20 text-center">
<h1 className="text-6xl font-bold mb-8">Users</h1>
<ul className="space-y-4">
{users.map((user) => (
<li key={user.id} className="bg-gray-100 p-4 rounded-md">
<h2 className="text-xl font-bold">{user.name}</h2>
<p>{user.email}</p>
</li>
))}
</ul>
<Link href="/">
<a className="mt-8 text-blue-600 hover:underline">Back to Home</a>
</Link>
</main>
</div>
)
}
export const getStaticProps: GetStaticProps = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users')
const users: User[] = await res.json()
return {
props: {
users,
},
}
}
This example fetches a list of users from a JSON placeholder API and displays them on a new page.
Wrapping Up
Congratulations! You've successfully set up a Next.js app with Tailwind CSS and TypeScript.
Happy Coding !!
Top comments (0)