Building a Github Repo Template Part 1: Next.js, React, and TypeScript

I'm finding myself needing to spin up a new project for a quick experiment and cringe at the thought of setting up my "Go To" tech stack from scratch for the Nth time. Luckily, Github has introduced template repositories and I think it is time to make one.

In this series of posts, I'll document the creation of the repository template. It will be fairly opinionated for my tech stack of choice as well as follow how I strategically set things up.

The Stack Covered in this Series

In this post, I will walk through setting up the base stack of React and Next.js with TypeScript.

Just want the Code? View the full changeset in this Github PR or check out the 0.0.1 release of the repository.

Initial Setup

Prerequisites

If you are following along:

  1. Make sure Node is installed. I am running v12.16.1. Check this by running node --version.
  2. Create a new Github Repository and check it out or simply create a new working directory for your project.
  3. In your working directory, run the following in the terminal
    npm init
    
    Answer the questions. The defaults are usually fine. This will create a package.json in your working directory and make it your project root. Note: You can manually change the values entered in this step later by editing the package.json

Install Next.js and React

Simply run the following in the terminal to install the core Next.js and React

npm install next react react-dom

I tend to like the consistency of running npm run dev to start my application across projects so I'll modify the "scripts" section of the package.json to be the following:

  "scripts": {
    "dev": "next",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

To start the application, run the following in the terminal

npm run dev

This should produce the below error because I have no pages yet for Next.js to render.

ready - started server on http://localhost:3000
Error: > Couldn't find a `pages` directory. Please create one under the project root
...

Creating The First Page

Next, I will create a simple page to have some code to work with to ensure the setup is good to this point. Note: That I am not using TypeScript yet, so I'll have to rename/modify this file later.

In the project root create /pages/index.jsx and add the below content.

import React from 'react';

const IndexPage = (props) => {
    let {greeting} = props;
    return (
      <div>
        <h1>{greeting}šŸ‘‹</h1>
      </div>
    );
  }

export async function getStaticProps() {
  return {
    props: {
      greeting: 'Hello Next.js',
    },
  }
}

export default IndexPage;

Now when I run npm run dev in the terminal, I see:

ready - started server on http://localhost:3000

Opening the browser to localhost:3000, produces: Screen Shot 2020-07-15 at 9.52.37 AM.png Next.js and React have successfully been installed. Celebrate.

Note: I added the call to the Next.js getStaticProps() method to illustrate passing props to a page, which will help us in later steps with TypeScript. Read more on getStaticProps

Introduce TypeScript

Next.js works really well with TypeScript. To get started, I simply need to create an empty tsconfig.json file in the project root by running touch tsconfig.json in the terminal.

Next run npm run dev, Next.js will produce a warning like:

ready - started server on http://localhost:3000
It looks like you're trying to use TypeScript but do not have the required package(s) installed.

Please install TypeScript, @types/react, and @types/node by running:

    npm install --save-dev typescript @types/react @types/node

As the message says, I need to install some things. To install these dev dependencies, simply run the following in the terminal:

npm install --save-dev typescript @types/react @types/node

Running npm run dev now produces a message like:

We detected TypeScript in your project and created a tsconfig.json file for you.
Your tsconfig.json has been populated with default values.

Next.js detected I want to use TypeScript and auto populated the tsconfig.json with some sane defaults specifically for working with Next.js, React, etc. If you are following along, feel free to open the tsconfig.json file and see the settings.

Convert The Next.js Page to TypeScript

Next I'll convert the page I created in previous steps to be written in TypeScript.

First, rename the pages/index.jsx file to pages/index.tsx. Based on the generated tsconfig.json, this will tell Next.js to interpret the syntax as TypeScript. When reloading the page, it should still work fine even though I have not written any TypeScript yet. This is due to the fact vanilla JavaScript is valid TypeScript code.

Next, I'll update the syntax of the /pages/index.tsx to add typings. Below is the modified TypeScript friendly version of the page with all the types overly explicit.

import React from 'react';
import {GetStaticProps, NextPage, GetStaticPropsContext, GetStaticPropsResult} from 'next';

interface IndexProps {
  greeting: string
}

const IndexPage:NextPage<IndexProps> = (props: IndexProps) => {
    let {greeting} = props;

    return (
      <div>
        <h1>{greeting}šŸ‘‹</h1>
      </div>
    );
  }

export const getStaticProps: GetStaticProps = async (context: GetStaticPropsContext): Promise<GetStaticPropsResult<IndexProps>> => {
  return {
    props: {
      greeting: 'Hello Next.js',
    },
  }
}

export default IndexPage;

Opening the browser to localhost:3000, gives the rendered result: Screen Shot 2020-07-15 at 9.52.37 AM.png TypeScript is installed and working great. Celebrate.

Note: I tend to be verbose with my typings and try to avoid inferred types where possible. This is personal choice, but I find it helps me understand the typings a lot better especially when I need to extend types.

Building and Running Build

The final step for this part of the series is to ensure I can create a production build of the application.

First, modify the "scripts" section of package.json to include the following build and start scripts.

  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start -p 8080",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

Then simply run

npm run build

This will produce output similar to:

Creating an optimized production build  

Compiled successfully.

Automatically optimizing pages  

Page                                                           Size     First Load JS
ā”Œ ā— /                                                          312 B            59 kB
ā”” ā—‹ /404                                                       3.25 kB        61.9 kB
+ First Load JS shared by all                                  58.7 kB
  ā”œ static/pages/_app.js                                       983 B
  ā”œ chunks/9eed07401741a3ab5c0a6c880a8e90d00a232a3c.36a881.js  10.7 kB
  ā”œ chunks/framework.c6faae.js                                 40 kB
  ā”œ runtime/main.99661a.js                                     6.28 kB
  ā”” runtime/webpack.c21266.js                                  746 B

Ī»  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
ā—‹  (Static)  automatically rendered as static HTML (uses no initial props)
ā—  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

Looking at the contents of the /.next folder, I see the above file structure. Next.js has compiled the TypeScript/React pages into vanilla Javascript that can now run with Node natively.

Lastly, I need to run the built application. I can do this by running the following in the terminal:

npm start

ready - started server on localhost:8080

Opening localhost:8080 in the browser, I can see I am now running the production build. Screen Shot 2020-07-15 at 9.52.37 AM.png Celebrate.

Commit and Designate as Template Repo

I'm done making code changes for the purpose of this part of the series. I have one final step, and that is to designate the Github Repository as a Template.

From the repository on Github, click on the Settings tab and select the checkmark next to "Template Repository" under the field to change the name.

Screen Shot 2020-07-15 at 1.46.54 PM.png

Once saved, the repository will now be available as a template to Create New Github Repository interface.

Screen Shot 2020-07-15 at 1.53.35 PM.png

Closing Thoughts

I've set up a basic Next.js project written in TypeScript. Here is a Github pull request covering all of these changes in this post or check out the 0.0.1 release of the repository

In the next post in the series, I will set up ESLint with VSCode to make sure the code is clean and also get the benefit of auto formatting, which I love.

Image Credit: "Nectarines" by animakitty is licensed under CC BY-NC-ND 2.0.

No Comments Yet