Building a water-drinking reminder with Next.js and Quirrel
Tags: nextjs, react, typescript, vercel
Published: 2020-10-15 08:34:03

---
title: Building a water-drinking reminder with Next.js and Quirrel
published: true
description: An introduction to Next.js and Queueing with Quirrel.
cover_image: https://unsplash.com/photos/h-9uis_AQic/download?force=true&w=1920
tags:
  - nextjs
  - react
  - typescript
  - vercel
---

Hi there! Welcome to the first ever post on the Quirrel blog!
Quirrel is an open-source task queueing service that's easy to use and sparks joy.
In this tutorial, we're going to use it to create a water drinking reminder - because if you're anything like me, it's easy to forget sometimes.

> Check out the finished version here: [water-reminder.quirrel.dev](https://water-reminder.quirrel.dev)

---

To follow this tutorial, you should already know a little bit about Next.js.
If you’re totally new to it, check out the [Next tutorial](https://nextjs.org/learn) first.

---

# Let's get started!

The first thing we're gonna do is to create a new Next.js project.

```sh
$ npx create-next-app water-reminder
```

Open up `water-reminder` in your favourite editor and run `npm run dev` to startup the development environment.

Take a look into `pages/index.js` and replace its content with the following:

```jsx
// pages/index.js
export default function Home() {
  return (
    <main>
      <h1>
        Water Drinking Reminder
      </h1>

      <p>
        I want to be reminded under the following e-mail:
      </p>

      <form
        onSubmit={(evt) => {
          evt.preventDefault();
          const formData = new FormData(evt.target);
          const email = formData.get("email");
          alert(email);
        }}
      >
        <input
          name="email"
          type="email"
          placeholder="E-Mail"
        />
        <button type="submit">
          Submit
        </button>
      </form>
    </main>
  );
}
```

It contains some markup and a simple form that lets you submit the e-mail you want to be reminded at.
At the moment, it will just alert the typed email.
In your browser, open up [localhost:3000](http://localhost:3000).
It should look similar to this:

![Submission Form](https://dev-to-uploads.s3.amazonaws.com/i/yv3au7nf6yv019tlqrqo.png)

## Submitting the form to the backend

Setup a new API Route by creating `pages/api/setupReminder.js` and adding the following code:

```js
// pages/api/setupReminder.js
export default async (req, res) => {
  const email = req.body;
  console.log(`I'll setup the reminder for ${email}.`);
  res.status(200).end();
}
```

Now instead of `alert`-ing the form value, let's post it to the newly created API route.
Go back to `pages/index.js` and replace the following:

```ts
// pages/index.js
onSubmit={(evt) => {
  evt.preventDefault();
  const formData = new FormData(evt.target);
  const email = formData.get("email");
- alert(email);
+ fetch("/api/setupReminder", { method: "POST", body: email });
}}
```

Submitting the form will now cause the e-mail to be printed to your development console:

![Screenshot 2020-10-13 at 16.19.35](https://dev-to-uploads.s3.amazonaws.com/i/2vobnhgwzxymupy2zw8c.png)

Now that we've hooked up the form with the API Route, let's get into Quirrel and E-Mail sending.

## Setting up Quirrel

Quirrel is a task queueing service.
It takes requests à la "call me back at /api/queue in 10 minutes", stores them and makes sure to call back `/api/queue` as requested.
What's awesome about Quirrel is that it can run fully locally using the Quirrel CLI:

```sh
$ npm install -g quirrel
$ quirrel
🎉 Starting the Quirrel Dev Environment 🎉
```

Now create a new queue by creating `pages/api/queues/reminder.js` and typing the following:

```js
// pages/api/queues/reminder.js
import { Queue } from "quirrel/next";

export default Queue(
  "api/queues/reminder", // the route it's reachable under
  async (recipient) => {
    console.log(`Sending an E-Mail to ${recipient}`);
  }
);
```

`Queue` takes two arguments: The first one is it's API route location, and the second one is the worker function.
Whenever a job is executed, the worker function is called.

To use our newly created Queue, simply import it from the API Route:

```js
// pages/api/setupReminder.js
+ import reminderQueue from "./queues/reminder";
// 👆 don't forget this

export default async (req, res) => {
  const email = req.body;
- console.log(`I'll setup the reminder for ${email}.`);
+ await reminderQueue.enqueue(
+   email,
+   {
+     id: email,
+     delay: "30min",
+     repeat: {
+       every: "30min",
+       times: 16, // 16 * 30min = 8h
+     },
+   }
+ );
  res.status(200).end();
};
```

Calling `.enqueue` will schedule a new job.
The first argument is the job's payload while the second argument contains some options:

- `id` prevents having multiple reminders for the same e-mail address
- `repeat` makes the job execute on twice an hour, for a duration of 8 hours
- `delay` adds an initial delay of 30 minutes, so the first job isn't executed immediately

To verify that this works, open up the Quirrel Development UI at [ui.quirrel.dev](https://ui.quirrel.dev/pending).
It will connect to your local Quirrel instance and show all pending jobs in the "Pending" tab:

![Quirrel UI](https://dev-to-uploads.s3.amazonaws.com/i/r8ekoytptmjnli7gcssn.png)

> If it doesn't connect, that may be because you're using Safari. Try a different browser instead.

Submitting your email to the form at `localhost:3000` will add a new job to the UI, and pressing "Invoke" will execute the job.
You'll now be able to see `Sending an E-Mail to XYZ` in your development logs.

Because it's a repeated job, it will be re-scheduled immediately, until it's been executed for the 16th time.

Before we proceed with the last part of the tutorial: Stand up, go to the kitchen and grab a glass of water 💧

## Let's hook up E-Mail!

Now that the Queue is working, let's hook up the final thing: E-Mail!

Run `npm install nodemailer` and add your SMTP setup code to your reminder queue:

```js
// pages/api/queues/reminder.js
import { Queue } from "quirrel/next";
+ import { createTransport } from "nodemailer";

+ const mail = createTransport({
+   host: "smtp.ethereal.email",
+   port: 587,
+   auth: {
+     user: "randall.renner66@ethereal.email",
+     pass: "Dp5pzSVa52BJwypJQm",
+   },
+ });

...
```

If you don't have any SMTP credentials at hand, you can get some demo ones [at ethereal.email](https://ethereal.email/create).

Then simply switch out the `console.log` call with a real email dispatch:

```js
...

export default Queue(
  "api/queues/reminder",
  async (recipient) => {
-   console.log(`Sending an E-Mail to ${recipient}`);
+   await mail.sendMail({
+     to: recipient,
+     from: "waterreminder@quirrel.dev",
+     subject: "Remember to drink some water!",
+     text: "..."
+   })
  }
);
```

That's it! Now our app is fully working.
It may not be the best water reminder service ever, but it's your very own one.

Here are some ideas to improve it further:

- Make duration and interval of the reminder configurable
- Allow users to unsubscribe using a link in the email
- Add some styles, maybe using [Tailwind CSS](https://tailwindcss.com)

Deploying this to production is easy using the [managed Quirrel service](https://quirrel.dev).
Simply follow this guide: [Deploying Quirrel to Vercel](https://docs.quirrel.dev/deployments/vercel)

# Conclusion

We've built a working water reminder in little under an hour.
You can see the finished project here: [quirrel-dev/water-reminder-demo](https://github.com/quirrel-dev/water-reminder-demo)

If you've got experience with well-known task queueing libraries like beanstalkd or SideKiq, you may have noticed how easy-to-use Quirrel is.
The highly integrated client libraries for popular frameworks and the managed solution available, Quirrel is a great choice for JAMStack users.

And if you want to host Quirrel yourself, the MIT License allows you to do so.