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
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 first.
Let's get started!
The first thing we're gonna do is to create a new Next.js project.
$ 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:
// 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.
It should look similar to this:
Submitting the form to the backend
Setup a new API Route by creating pages/api/setupReminder.js
and adding the following code:
// 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:
// 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:
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:
$ 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:
// 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:
// 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.
It will connect to your local Quirrel instance and show all pending jobs in the "Pending" tab:
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:
// 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.
Then simply switch out the console.log
call with a real email dispatch:
...
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
Deploying this to production is easy using the managed Quirrel service.
Simply follow this guide: Deploying Quirrel to 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
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.
Top comments (1)
Got it working !
Daniel :)