My First PWA in NextJS
Tags: webdev, beginners, pwa, tutorial
Published: 2024-01-15 12:56:21

Have you ever fallen in love with a character from a book or movie so much that you want to talk them all the time? That's my feeling towards Rust Cohle from True Detective S1. While rewatching season one, I started to look for a quote generator for the character, Rust. I couldn't find anything that I was looking for, so I decided to build one!

## Building a Quote Generator
In this, we're going to build a quote generator that prompts subscribed users with a message to check for the quote of the day. There's going to be a few steps, but this is how we can do this:

- Build out an API with pre-loaded quotes
- Build a NextJS site to do API fetch calls and manage the cached data
- Add on a PWA library to handle the subscriptions for users

## Building a REST API
The first to do in this project is to build out an REST API using Node with an Express server. This will be a quick overview of the steps. If you want to go deeper into building a REST API, I recommend reading [this article from Postman](https://blog.postman.com/how-to-create-a-rest-api-with-node-js-and-express/).
You'll start by creating a directory for your project and then use `npm init` to create a Node application. You'll install express with `npm install express` . Go ahead and open up your project in your code editor. You'll add a new file and name it app.js. This will be your working app file where you'll want to set up the server and also include your routes. You can see my app.js file on [Github](https://github.com/ryanjames1729/rust-cohle-quotes/blob/main/app.js).
To get everything running for testing, you'll want to add the following code:

```
const express = require('express');
const app = express();
app.use(express.json());
const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`Server Listening on PORT: ${port}`);
});
app.get("/", (request, response) => {
    response.status(200).json({
        message: "Waiting on Requests"
    });
});
```
You have the option of using multiple GET routes or one depending on your project. I have two, one for testing which is my "/" route and then another one for returning quotes "/new-quote". My "new-quote" route will go through my array of quotes and then find one randomly. So then the API will return the result of that call.
Once you get everything running how you want it, it's time to get it online. If you already have a [Heroku](https://www.heroku.com/) account or some other cloud based hosting provider, then go that route. I went with a free account on [Render](https://render.com/). The docs on Render were clear and it made it easy to use my repo that I had on Github and have it online.

## Using a NextJS App to Fetch Data
Before we get into this, let's clear the air on NextJS. I understand that using a React framework for this simple project is bloated. I know that a simpler way would be to use vanilla javascript and manipulate the DOM for this. The reason I pulled for NextJS is that I'm familiar with it, I wanted to use the cache management from NextJS, and I knew that adding on the PWA capabilities would be easy with NextJS.
I created a project by using the NextJS starter with TailwindCSS. I wasn't really concerned with the look and feel of this project. I wanted to create this more of a 'proof of concept' than anything. TailwindCSS made it easy to get things styled quickly without having to write any CSS classes from the start. Once I got the project going, I wanted to do a couple things at the beginning. I wanted to create a 404 page in the app folder. I created a not-found.js file for my 404 route. Then on the page.js file in my app folder, I deleted most of the content. 
For the page.js file, I used the fetch API to send a request to the API that I was hosting. Then, I could just insert this into the JSX for my page. I want the page to just say the quote. I didn't wan't anything else really on the page. This makes the return for the default function Home() very short.
The next piece that I wanted to implement since I was using NextJS, was to take advantage of the cache management. Since I wanted this to be a 'Quote of the Day' app, I only wanted a new quote to appear each day. To do this, I used the revalidate feature in NextJS. If you haven't used this before, when you use the fetch API, you can add a revalidate parameter to it. This will check the cache and use the time that you specifiy to determine if the cache is stale or not. So based on that time, I can have what is fetched replace the current cache. And voila, a quote of the day using a time of 86400 seconds. I backed mine down to 72000 in case someone checks it every 22 hours and not right on 24 or later.

## Time for a PWA
This was my first time trying to take a current site and implement it as a PWA. The reason why I was wanting a PWA was because I want users (mainly myself) to be able to subscribe to the site and get daily notifications to check the quote of the day. I went with OneSignal to manage the notifications. I know I could have done it easier by adding my own service workers, but I since this was my first time, I wanted something easier for me.
After you create your account in [OneSignal](https://onesignal.com/), you then can create a new app. After you get your website linked with your OneSignal account, you can download the OneSignal SDK. By putting the OneSignal SDK into your project directory, that takes care of the subscriptions for you. OneSignal has really good documentation on all of this. I followed this instructions on their site and it took maybe 10 minutes to set up. OneSignal has a great dashboard that allows you to manage users and send out notificaiton messages. SInce I wanted this to be a daily app where users would get a notification each day, I created an Automated message. By creating an Automated message for users, this scheduling of sending the message would be done. I wouldn't have to try to figure out how to trigger an event on OneSignal with an external tool. OneSignal takes care of all of that.

## What's Next?
This was a fun project. I can see this being a bigger project or a project that can easily be replicated. Often students in school are studying a famous figure in history where there are tons of quotes that can be set up in an API. I think it would be a cool idea for while a teacher is teaching about this person, they could have a daily or hourly quote app that they pull up or allow students to subscribe to. Also, I've seen some neat projects where people are not just using a quote api, but using AI tools to generate new quotes each day based on their data set of available quotes. All fun projects!

*This article was originally pubblished on [ryan-james.dev](https://www.ryan-james.dev/articles/blog/my-first-pwa)*