skip to content
f1sh

NextJS's "full-stack"

/ 4 min read

Prelude

NextJS is a React framework that enables you to build full-stack web applications. We’ve known React to be a library for frontend development and, for some, seeing the term “full-stack” for a React framework might come confusing. This post talks a bit about the server or the backend side of NextJS and some of its specific features that can account to it being full-stack framework. Whether NextJS is fit to be called as such is a debate outside the scope of this post.

”Runs on the Server”

Ever come across the “this runs on the server” while reading the docs or blogs? That’s because NextJS indeed parses your application and determines what to run in the server and in the client.

To illustrate, let’s look at a couple of features from NextJS:

  1. API routes
  2. getServerSideProps

API Routes

For API routes, anything in the folder pages/api will be accessed as api/* endpoints hence it will be like the familiar /api/<endpoint> you typically implement in other backend server frameworks like Spring Boot or FastAPI.

Here’s a snippet from the docs:

import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}

According to NextJS:

A good use case for API Routes is handling form input. For example, you can create a form on your page and have it send a POST request to your API Route. You can then write code to directly save it to your database. The API Route code will not be part of your client bundle, so you can safely write server-side code.

So those pages/api codes that implement the logic that handle API requests will not be part of the client bundle. Instead, they are server side code which, for example, can “directly save … to your database” among other things you typically implement in an API server.

That means, if you have implemented API endpoints before, you will find NextJS’s API for the API Routes and its purpose familiar.

getServerSideProps

Now let’s look at getServerSideProps as another example. This is a special function that runs on the server. As NextJS docs put it:

  • getServerSideProps runs on the server.

  • When a user visits the page through next/link or next/router, Next.js sends an API request to the server, which runs getServerSideProps.
  • You do not have to call a Next.js API Route to fetch data when using getServerSideProps since the function runs on the server. Instead, you can call a CMS, database, or other third-party APIs directly from inside getServerSideProps.

Note the last point that says it runs on the server and that you can call a CMS, database or other third-party APIs from the function. This function, when exported from a page, will pre-render the page. From NextJS Docs:

pages/index.tsx
import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getServerSideProps = (async () => {
// Fetch data from external API
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo: Repo = await res.json()
// Pass data to the page via props
return { props: { repo } }
}) satisfies GetServerSideProps<{ repo: Repo }>
export default function Page({
repo,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<main>
<p>{repo.stargazers_count}</p>
</main>
)
}

The above page will be pre-rendered as a getServerSideProps is exported in the page. This is different from API routes where all the handlers in pages/api will be accessible via /api endpoint. In this case, we leverage NextJS’s Server-Side-Rendering (SSR) capabilities by, first running the getServerSideProps function and then, server-render the page.

If I may, this is akin to PHP server-rendered pages before it passes the HTML to the client.

So, is NextJS full-stack?

Since NextJS supports client-side development with React, and also allows development of endpoints via its API routes as we’ve seen above, and these endpoints are able to talk to third-party APIs or its database we can say NextJS supports building a full-stack application.

Now others would point out its capability to be a “backend” given the arguably richer and more performant options like Lavarel or Go servers especially in more compute-heavy operations. And that the backend is preferred to be decoupled from the frontend. That perhaps is already a matter of the nature of application being built. Nevertheless, such setup is possible and well discussed in the community with others suggesting the Backend-for-Frontend BFF pattern which we’ll talk about in another post.