Building webapps fast with Next.js app router

Introduction

Setting up webapps can be time consuming, particularly when the goal is to build a quick proof of concept of something. One challenge I find is that I spend most of my time setting up the project, leaving little time to actually build the functionality on top of it.

I've recently been exploring Next.js as a framework for creating full stack applications easily and I've found a way of quickly setting up a new project by combining it with Tailwind CSS for styling.

From my exploration I've found a set of tools that provide a good baseline for building web apps, they are:

  • Next.js which is a framework for building full stack React applications, it packages a lot of things together (such as a router) that makes it a lot easier to get started without having to spend time deciding which libraries to use and how to integrate them
  • Typescript which makes it easier to write error-free code by adding types, allowing you to build faster while reducing the chance of introducing bugs
  • Tailwind CSS is a CSS framework that works well with the Next.js's new app router, which uses React Server Components. Tailwind does have a learning curve, but with a understanding of the fundamentals it can allow rapid styling of components.
  • Prettier is a automatic code formatter that reduces the amount of time you spend manually formatting code by automatically formatting code when you save the file.

With all that in mind, lets setup a new project.

Setting up a project

To setup the project we are going to use create-next-app, which is a tool that easily allows bootstrapping new Next.js applications. create-next-app has a few CLI flags we can pass to streamline the process.

To get started open a terminal and cd to where you keep your projects, for example cd ~/projects then copy and paste the below command into the terminal

pnpm create next-app \
	--typescript \
    --tailwind \
    --eslint \
    --app \
    --src-dir \
    --import-alias "@/*"

The above command sets up Typescript and Tailwind by default and uses the new app router. When ran you will be prompted to enter a project name

? What is your project named? › my-app

After the command finishes, open the project in vscode with

code my-app

Setting up Prettier for automatic code formatting

Prettier takes a lot of the manual work out of formatting code by automatically formatting code when you save. Its really quick to setup and saves heaps of time.

  • Install dependencies
    pnpm i prettier eslint-config-prettier
  • Create a .prettierignore
    .next
    node_modules
    pnpm-lock.yaml
  • Create a .prettierrc.json config file for Prettier
    {}
  • Add plugin to the extends array in .eslintrc.json
    {
      "extends": ["next/core-web-vitals", "prettier"]
    }
  • Add a format NPM script
    {
      "scripts": {
        "format": "prettier --write ."
      }
    }

Create a VSCode workspace

VSCode has a concept of a per project workspace, which allows you to store editor configuration in the repo, which is useful if multiple people contribute to the code (as everyone will have the same base config). It also has some handy features such as defining a set of recommended extensions to prompt the user with when they open the project.

  • In VSCode, click "File" > "Save Workspace As.." and choose the default name
  • Create a .vscode/settings.json
    {
      "editor.formatOnSave": true,
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    }
  • Create a .vscode/extensions.json
    {
      "recommendations": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss"
      ]
    }

Remove unneeded boilerplate

create-next-app will automatically generate some boilerplate, I find it easiest to delete it, so you can start with a blank slate. Luckily deleting the boilerplate is really quick.

  • Remove unneeded icons
    rm public/*
  • Replace src/app/globals.css with
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
  • Replace src/app/page.tsx with
    export default function Home() {
      return <main></main>;
    }
  • Replace tailwind.config.js with
    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
        "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
        "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
      ],
      theme: {},
      plugins: [],
    };

Run the app

With all the configuration now done, everything is ready to go to build an app. The app can be started with pnpm dev. Once ran you should see a blank screen, add some content to the src/app/page.tsx file and you should see it reflect on the page.