Take the Next.js Step in Web Development

DRAGON2002
tech@iiit-gwalior
Published in
12 min readDec 12, 2021

A while ago the idea of creating my own portfolio website popped into my head, having dabbled in web development for quite a while I thought it was about time I had my own custom made website to showcase.

So in order to make the site I first had to decide upon the libraries and frameworks, I would use in order to do so (or do it the old fashioned way, using the holy trinity of web dev i.e. HTML, CSS and you guessed it JavaScript).
As it was pretty obvious that all I really needed was just a frontend, as I didn’t want to store any such data so as to create and handle a complete backend and database, I ended up choosing *drumrolls* React!

The choice was mainly based on the fact that I had a fair bit of experience already with React, it has been and shall even continue to be the de facto standard for full-fledged frontends that allow component reusability, with proper state management and the ability to handle large scale projects!
…. wait a second ….
large scale projects? proper state management? component reusability? That does not sound anything like a simple frontend portfolio website at all, so, the only reasonable argument left was the comfort I felt with the React like syntax and structure.

This dilemma got me thinking, was a comfort as a reason to use React really satisfactory? Now, the solution to this dilemma can vary from person to person, but for me using React for such a small and simple site was simply put overkill.
So I started looking for an alternative (and thank God I did), which ended up being the Next best thing (haha get it ? …. no ? …. *coughs* okay moving on …. 😅) that is Next.js so let’s dive into it in a bit more detail, shall we?

What is Next.js?

In official terms, Next.js is an open-source development framework created by Vercel built on top of Node.js enabling React-based web applications functionalities such as server-side rendering and generating static websites.

Which in layman terms means that Next.js is a framework that allows developers to create sleek, stylish, optimized and most importantly fast (fast as in “I am speed” levels of fast) websites all based on the standard React syntax, functionality and structure (albeit with a few differences), it also allows the creation of applications with Server Side Rendering (SSR) and Static Site Generation (SSG).

Now you might ask what is SSR and SSG and why should you care about them?
Well, in React due to the dynamic nature all the jsx is rendered on the browser side i.e. client side, the server in those cases only deals with providing data as and when required, and when the page is accessed on the browser the frontend then creates the requested page. Moreover, these pages display data based on the user trying to access the page and how they interact with the page, hence is not always the same for all users.

Server Side Rendering allows the entire page to be created, structured and styled on the server side instead of the client side this leads to less data fetching from client to server as the entire site is created at once instead of a route basis and also greatly improves Search Engine Optimization (SEO, which is responsible for getting the site highlighted on a browser search) as the client side now simply needs to display the HTML files on the browser. Static Side Generation entails the creation of pages that have static content i.e. the page will always be the same no matter what interactions the user does with the page, unless and until the code for the page is changed (this is how websites were before dynamic interactions in websites were introduced).

Now that the formal definitions are out of the way, let’s get our hands dirty with some actual code now, shall we?

Creating our first Next.js app

For the purposes of this guide, I would be using VSCode as my code editor although you can use whichever code editor you prefer even those that are not really meant for coding in the first place (I’m looking at you notepad), simply make sure that you have npm installed and as for pre-requisites, there aren’t any although prior knowledge of React would be really handy.

When you are all setup, navigate to an empty folder where you want to create the project and open up a terminal/cmd session there and type -

npx create-next-app .

This will create and setup a boiler Next.js app along with all the default required dependencies.

Now in order to run the app in development mode in the same folder in the terminal type -

npm run dev

This will startup the development server on port 3000 on your localhost. Navigate to the url and you will find the default Next.js welcome page which looks like -

If we take a look at the boilerplate code that create-next-app created for us it looks like -

Default Next.js boilerplate code

Now let’s take a look at all this scary starter code and demystify them.

Of all the files “pages”, “public” and “styles” are the only three folders that we need to concern ourselves with at this point as everything else generated are simply config and git files and need not be tampered with.

The “public” folder will contain all the public media such as images, svgs, icons etc. Anything you put here will be accessible to anyone visiting the page.

The “styles” folder will contain all the CSS files used in the project and would be imported into respective files from here.

Now comes one of the most important if not the most important aspects of Next.js, the pages folder. This folder is responsible for routing in Next.js applications. Any JS file we create inside of that folder will become a route in our application with the route name being the same as that of the file created and when we navigate to that route components of that file will get rendered. Moreover, any folder we create inside the pages folder will become a nested route.
As an example in the starter code inside the api folder, we have a file named hello.js which simply returns a name. So, if on your browser you go to -

http://localhost:3000/api/hello####
http://localhost:3000 -> Base url
/api -> Nested route folder
/hello -> File to access inside the nested folder
####

We get the following text on the page -

This is because we asked the browser to render the hello.js file that was nested inside of the api folder, the hello.js file created by default returns this very response on being rendered.
Similarly, we can create more nested subroutes by creating more nested folders and every JS file will correspond to an url endpoint. Also, index.js in any folder will correspond to the “/” endpoint for that route i.e. the default page.

A special file that we still haven’t talked about yet is the “_app.js” inside the pages folder, this is the global file for our Next.js application and wraps around each and every component and page in our application and explicitly renders all child components. Although very abstract, for the purposes of this guide you can think of this file as the global structure i.e. a container for every page of our application hence any change or additions we make here will be reflected on each and every page such as adding a header or footer here will lead to a header or footer being present on all pages.

Creating a Blog Reading Site

In this guide, we will be creating a blog page with a list of blogs to select from and with each blog having its own page. We will be using dummy data for the blogs which we will get from an external API.

First of all, delete the Home.module.css file in the styles folder as we will be creating our own styles and in the index.js file inside the pages folder replace the code so it looks like this -

const Home = () => {
return ( <div> HELLO NEXT ! </div> )}export default Home

Now if we go to http://localhost:3000/ we will get “HELLO NEXT !” as the response -

Page at http://localhost:3000/

Now we will start creating the components that we will be needing so create a new folder named “components” in the same folder level with the folders pages, styles and public i.e. at the root of the project. Inside the components, the folder creates a file named “BlogList.js” and another file named “Blog.js”.

Inside the BlogList.js file, we create the BlogList component as such -

import Blog from "./Blog"const BlogList = ({blogs}) => {    return (        <div>            {blogs.map((blog) => (                <Blog key = {blog.id} blog = {blog} />            ))}        </div>    )}export default BlogList

Inside the “Blog.js” file we create the Blog component as such -

const Blog = ({blog}) => {
return (
<div> <h3>{blog.title} &rarr;</h3> <p>{blog.body}</p> </div> )}export default Blog

Data Fetching in Next.js

In Next.js we have three main components related to data fetching which are actually predefined functions namely getServerSideProps(), getStaticProps() and getStaticPaths(). All three of these functions are async by nature and need to be defined as such, simply exporting them in the respective file where they are used is sufficient to inform Next.js to call these functions for fetching data.

getServerSideProps() when used will cause the page to re-render with the data provided by the function whenever a request to the page is made.
getStaticProps() when used will prefetch all the data and convert them into static pages and simply render the same page whenever a request is made without fetching any new data. The API where we are fetching the data must be active during the building process so internal APIs won’t work.
getStaticPaths() is used alongside with getStaticProps() in order to provide static routes to the data fetched so each data item can have its own individual page to render. Cannot exist without getStaticProps().

getServerSideProps() when used is responsible for Server Side Rendering (SSR), whereas when getStaticProps() and/or getStaticPaths() are used are responsible for Static Site Generation (SSG).

For this guide we will be going the Static Site Generation way, hence we will be using getStaticProps() and getStaticPaths(). If Server Side Rendering is what intrigues you then I suggest you to take a look at the official Next.js documentation to learn how to use getServerSideProps() instead (preferably after you are done reading this blog).

Update the “index.js” file in the pages folder to the following -

import BlogList from "../components/BlogList"const Home = ({blogs}) => {    return (        <div>            HELLO NEXT !            <BlogList blogs = {blogs} />        </div>    )}const getStaticProps = async() => {    const res = await fetch(`https://jsonplaceholder.typicode.com/posts?_limit=6`)    const blogs = await res.json()    return {        props : {            blogs        }    }}export {getStaticProps}export default Home

Here we are creating and exporting the getStaticProps() async function to fetch the data and passing the json response to props which gets passed to the Home component which is then passed to the BlogList component. Now if we go to http://localhost:3000 we find the following page with data -

Page at http://localhost:3000

Creating Routes for Pages

Now we will create routes for all the blog posts that we have fetched from the API, in order to do we will create the route first, so create a blogs folder inside the pages folder to create the /blogs nested route, within blogs folder create another folder named [id] and within that folder create index.js.

This /blogs/[id]/index.js structure denotes that for different blogs they will have different ids that are represented by [id] and for every such blog we will render the index.js, i.e. depending on id different static blog page route will be created.

Inside index.js inside the [id] folder, we put the following code -

const BlogPage = ({blog}) => {    return (        <div>            <h1>BLOG {blog.id}</h1>            <h2>{blog.title}</h2>            <p>{blog.body}</p>        </div>    )}const getStaticProps = async(context) => {    const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${context.params.id}`)    const blog = await res.json()    return {        props : {            blog        }    }}const getStaticPaths = async() => {    const res = await fetch(`https://jsonplaceholder.typicode.com/posts`)    const blogs = await res.json()    const ids = blogs.map(blog => blog.id)    const paths = ids.map(id => ({params : {id : id.toString()}}))    return {        paths,        fallback : false    }}export {getStaticProps}export {getStaticPaths}export default BlogPage

Here we define and export both getStaticProps() and getStaticPaths() async functions.
getStaticPaths() fetches all the data and creates individual URL paths for all of them depending on the id, fallback if set to false shows a loading icon while the page is being loaded.
getStaticProps() fetches the blog with the id as specified in the URL by the [id] route parameter, this is accessed inside the function by passing the context object to it which holds the id as its parameter accessed from “context.params.id” this blog data is passed as a JSON prop to the BlogPage component where it is rendered.

Now if we navigate to http://localhost:3000/blogs/1 we get a page with blog data from blog post 1 and similarly for all other blog ids.

Just for the sake of completeness, I will also include the getServerSideProps() async function here although it has not been used in the project. It looks like -

 const getServerSideProps = async(context) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${context.params.id}`)
const article = await res.json() return { props : { article } }}
export {getServerSideProps}

This is very (if not completely) similar to the getStaticProps() async function the only difference being that static paths would not be created in advance instead they would be created whenever they are requested and will re-fetch data from the server due to SSR.

Creating Links to Different Pages

In order to link to pages within the Next.js application, we use the default “Link” tag present inside Next.js, open index.js inside the pages folder and update the code as -

import Link from "next/link"const Blog = ({blog}) => {    return (        <div>            <Link href = "/blogs/[id]" as = {`/blogs/${blog.id}`}>                <div>                    <h3>{blog.title} &rarr;</h3>                    <p>{blog.body}</p>                </div>            </Link>        </div>    )}export default Blog

We import the Link component from next/link and wrap our div with it similar to an anchor tag and we pass in the “href” to map it to our project directory structure with the actual url to link to passed in with the “as” parameter.

Now when we click on any blog on http://localhost:3000 it will direct us to the appropriate url for that blog http://localhost:3000/blogs/id where id the id of the blog clicked on.

Styling the Site

Our application is now complete and works as expected but it still looks dull, so let’s add some styling to it.
In the styles folder the “Global.css” file is imported into the “_app.js” file which is the wrapper component for all pages, hence if we make any changes in the “Global.css” file then those changes would be reflected in all the pages.

We will only be styling the Blog component so create a “Blog.module.css” file in the styles folder, and fill it with -

.container {    text-align: center;    margin: 100px;    border: 2px solid black;    border-radius: 10px;    font-size: large;    padding: 20px;}.container:hover {    cursor: pointer;    color: white;    background: black;}

Now update your “Blog.js” in the components folder to -

import Link from "next/link"import styles from "../styles/Blog.module.css"const Blog = ({blog}) => {    return (        <div className = {styles.container}>            <Link href = "/blogs/[id]" as = {`/blogs/${blog.id}`}>                <div>                    <h3>{blog.title} &rarr;</h3>                    <p>{blog.body}</p>                </div>            </Link>        </div>    )}export default Blog

Here we import “styles” from the corresponding CSS file and set the “className” of the tag we want to style to the styled class in the CSS file, “container” in this case. This will apply all styles of the CSS class to the respective component.

Now our home page looks like -

Our first Next.js application is now complete!
To host it I would recommend using Vercel hosting service as their hosting service is very friendly towards Next.js applications (I mean Next.js was created by Vercel so what else did you expect ?), simply push the code to GitHub, import it to your Vercel account and build it, and just like that your application would be hosted.

Final Thoughts

I have only covered the basics of Next.js in this guide, for those interested there are still many things to explore such as image optimization, exporting static files, head tags, SEO, API creation etc. This is just the tip of the iceberg and there is much more to learn.

I suggest you look at the official documentation to further your understanding.

All in all, for people familiar with web development Next.js is an amazing addition to your toolkit, and for people just getting started, it is a great starting point.

I guess I have ranted enough so that’s about it for this blog, stay tuned for the Next one! (okay I will stop with the Next.js puns now haha 😂).

--

--