The Next.js App Router: Setting up a “Hello, World!” web app

Tutorials
Author

David Wu

Published

June 25, 2023

In this article, we set up a “Hello, World!” web app with Next.js and Tailwind CSS.

We will begin by creating a new Next.js web app using create-next-app. Here, create-next-app will set up Tailwind CSS for us.

Following that, we will simplify the provided source code so that our web app frontend displays the text “Hello, World!”.

Finally, we will use Tailwind CSS to apply some basic styling to the text “Hello, World!”.

System requirements

Next.js requires Node.js version 16.8 or later. You can check what version of Node.js you have installed by running the following command:

node -v

If you don’t have version 16.8 or later installed, go and do this before proceeding.

Creating a Next.js web app using create-next-app

To begin, using the terminal, we first change the working directory to the folder (e.g. projects) in which we will create a subfolder (e.g., projects/hello-world-nextjs-tailwind-css) to store all of our web app’s files. Running create-next-app will create this subfolder for us.

To create a new Next.js web app using create-next-app, we run the following terminal command:

npx create-next-app@latest

In the terminal, you’ll be presented with a series of questions. For our purposes here, we respond to the set up questions as follows:

  • What is your project named? hello-world-nextjs-tailwind-css
  • Would you like to use TypeScript with this project? No
  • Would you like to use ESLint with this project? No
  • Would you like to use Tailwind CSS with this project? Yes
  • Would you like to use src/ directory with this project? No
  • Use App Router (recommended)? Yes
  • Would you like to customize the default import alias? No

Out of the box, we use JavaScript instead of TypeScript. We use Tailwind CSS. We use the App Router.

For simplicity, we do not use ESLint. We do not use the src/ directory. We not customise the default import alias.

Following this, create-next-app will proceed to automatically download and install the dependencies for our Next.js app, including Tailwind CSS.

The file structure of our create-next-app project

Once create-next-app has successfully executed, we change the working directory into the folder containing our web app’s files (e.g., hello-world-nextjs-tailwind-css).

We see that create-next-app has created a number of files and folders.

The initial file structure of our web app

This project structure and the provided files are a strong starting point for building a web app. Rather than starting from scratch, we can edit the provided files and add and delete our own files.

In addition, we benefit from unique Next.js features supported by the App Router. We’ll gradually explore some of the unique features Next.js offers as the book progresses.

Deploying our web app locally

To start the development server and deploy our web app locally, we simply run the following command:

npm run dev

We can now open our web app locally in a web browser at the address http://localhost:3000.

The start page for create-next-app at http://localhost:3000

Simplifying the web app to display “Hello, World!”

Next, we edit our project files to simplify the web app frontend to display the text “Hello, World!”. When changes to our project files are saved, Next.js will automatically re-render our web app.

We start by editing the root page, which corresponds to http://localhost:3000.

When using the Next.js App Router, the pages of our web app are located in the app directory. The root page corresponds to app/page.js.

We simplify the contents of page.js to the following:

export const metadata = {
  title: "Hello, World!",
  description: '"Hello, World!" web app with Next.js and Tailwind CSS',
};

export default function Home() {
  return (
    <main>
      <h1>Hello, World!</h1>
    </main>
  );
}

Our web app will re-render, but the styling will be white text against a black background. We simply want to display the text “Hello, World!” in black against a white background.

To achieve this, we open app/globals.css and delete all the contents within this file from the fifth line onwards. The first three lines are needed for Tailwind CSS. As is customary, we let the last line of the file be a new line.

The file globals.css should now only contain the Tailwind CSS directives:

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

And the root page should re-render with the desired outcome:

Our “Hello, World!” Next.js app with Tailwind CSS

We also tidy up the public folder which is used to store static assets such as images. We delete the following files from the public folder that were used in rendering the original root page but are now no longer of use:

  • next.svg
  • vercel.svg

Using Tailwind CSS in our project

To use Tailwind CSS in our project, we add the provided utility classes directly to the className attribute of the HTML elements that we would like to customise.

There’s no need for a separate CSS style sheet and there are utility classes for almost every CSS attribute. The Tailwind CSS official docs are the very best source for finding the utility classes you need. You’ll get the hang of it in no time!

Let’s make the “Hello, World!” text larger (text-4xl), adjust its weight to bold (font-bold) and change its colour to blue (text-blue-600).

To do this, we specify utility classes in the className attribute of the opening tag of the h1 element:

<main className="h-screen flex flex-col justify-center">
  <h1 className="text-center text-4xl font-bold text-blue-600">
    Hello, World!
  </h1>
</main>

This will achieve the desired final result.

Our “Hello, World!” web app with Next.js and Tailwind CSS

Backend API endpoints in Next.js

Before we conclude this article, let’s create a simple backend API endpoint in Next.js. This shows how Next.js enables us to build fullstack web apps with React.js.

Suppose we want to create a backend API endpoint that can be accessed at http://localhost:3000/api/hello.

In Next.js, all the logic for the route handlers for our API endpoints live in files named route.js nested in the directory app/api.

For example, to create the desired endpoint we put logic for our route handler in the new file app/api/hello/route.js.

This achieves two purposes:

  • The file path app/api/hello/route.js corresponds to the API endpoint http://localhost:3000/api/hello. Similarly, the file path app/api/bye/route.js would correspond to the API endpoint http://localhost:3000/api/bye
  • The file route.js contains the logic for our route handlers that define how HTTP requests to our /api/hello endpoint should be handled

Let’s create the file route.js located at app/api/hello/route.js, with the following contents:

export function GET() {
  return new Response(JSON.stringify({ message: "Hello, World!" }), {
    status: 200,
    headers: { "Content-Type": "application/json" },
  });
}

To see what happens when we send a request to this endpoint, open http://localhost:3000/api/hello in your browser. The response returned by the browser contains the following text in JSON format:

{"message":"Hello, World!"}

In app/api/hello.js, we have a function GET(), which is a route handler for HTTP requests with the method GET sent to the API endpoint http://localhost:3000/api/hello.

Upon receiving a request, the route handler returns a response with the following properties:

  • Body: The response has a JSON body with a single property that has the name message and the value "Hello, World!"
  • Status code: The response has the success HTTP status code 200
  • Content type: The response indicates that it has a body containing JSON content. Put another way, it has its "Content-Type" specified as "application/json"

More generally, we could similarly use this approach to define route handlers for other common HTTP methods such as POST, PUT, DELETE and PATCH.

In addition, for our route handlers, we can optionally specify a request object argument such as GET(request) or POST(request).

The general pattern here is that the user’s browser sends a request and the incoming request triggers a route handler on the server. Information on the request may then be used by the route handler to prepare and process the response, which is finally returned to the browser.

Resources to learn more about Next.js and Tailwind CSS

The best places to learn more about Next.js and Tailwind CSS are the officials docs:

They provide the most authoritative and up-to-date information on how to use these technologies. The docs are useful as both a learning resource and a reference. Other than the official docs, there are of course many learning resources elsewhere, including on YouTube, developer education sites and personal blogs.

Summary

In this article, we covered the following topics:

  • Setting up a “Hello, World!” web app with Next.js and Tailwind CSS using create-next-app
  • Simplifying the starter web app to display the text “Hello, World!” and styling this text using Tailwind CSS
  • Additionally, we also discussed backend API endpoints in Next.js

👋 Thanks for reading

A picture of the author of this blog.

The goal of this blog is to create useful content for devs and share my own learnings.

My current passion project is to help devs learn how to use the OpenAI API.

Join my email list to hear about new content. No spam, unsubscribe at any time.