Skip to content

Commit 91a3d93

Browse files
KevinEdrySkn0tt
andauthored
added nextjs 13 app router native support & docs improvements. (#1141)
## Summary This PR aims to revise and add two main things: - Bring native support for Nextjs 13 app router to Quirrel - #1138 - Improve the docs experience since the hosted version of Quirrel isn't available anymore ## Nextjs 13 App Router Because Nextjs 13 now expects a named method function as a route handler (POST, GET etc..), we need to provide it as part of the `Queue` and `CronJob` methods, we also want the queue instances themselves, so I've made it so it would be accessible via object destructuring, that way we can export both `POST` and the queue instance in one go, and alias the queue instance with a meaningful name. Queue Usage: ```typescript export const { POST, queue: sampleQueue } = Queue( "/api/queues/sample", (payload) => { ...logic goes here }); await sampleQueue.enqueue({ jobData }); ``` CronJob Usage: ```typescript export const { POST } = CronJob( "/api/queues/sample", "0 0 * * 1" (payload) => { ...logic goes here }); ``` I've added some docs changes as well to explain the usage of the new queue api. **The object destructuring is the best way I could think of to keep the named export function `POST` and still have a meaningful name for the queue instance, if you can think of a better implementation for this please let me know!** ## Changelog: ### code - added new `next13.ts` file to support nextjs 13 app directory natively. ### docs - added to proper documentation for all of the Nextjs changes. - added new "Development" category which explains how to run the Quirrel instance in a docker compose, or as a standalone instance. - added a new and improved "Deployment" category with several guides on how to deploy quirrel (docker, railway, fly and vercel). - removed the old "Deploy" page. --------- Co-authored-by: Simon Knott <[email protected]>
1 parent 9344abf commit 91a3d93

File tree

13 files changed

+422
-189
lines changed

13 files changed

+422
-189
lines changed

docs/docs/api/next.md renamed to docs/docs/api/next.mdx

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,44 @@
1-
---
2-
title: Next.js
3-
---
1+
import Tabs from "@theme/Tabs";
2+
import TabItem from "@theme/TabItem";
43

5-
```ts title="pages/api/someQueue.ts"
6-
import { Queue } from "quirrel/next";
4+
# Next.js
75

8-
export default Queue(
9-
"api/someQueue",
6+
<Tabs>
7+
<TabItem value="app" label="App Router">
8+
9+
```typescript title="app/api/queues/sample/route.ts"
10+
import { Queue } from "quirrel/next-app";
11+
12+
export const sampleQueue = Queue(
13+
"api/queues/sample",
1014
async (job, meta) => {
1115
// do something
1216
}
1317
);
18+
19+
export const POST = sampleQueue;
20+
```
21+
22+
Creates a new Queue.
23+
Make sure to export it from a [Route Handler](https://nextjs.org/docs/app/building-your-application/routing/router-handlers), otherwise it won't work.
24+
25+
</TabItem>
26+
<TabItem value="page" label="Pages Router">
27+
28+
```typescript title="pages/api/queues/sample.ts"
29+
import { Queue } from "quirrel/next-pages";
30+
31+
export default Queue("api/queues/sample", async (job, meta) => {
32+
// do something
33+
});
1434
```
1535

1636
Creates a new Queue.
1737
Make sure to export it from an [API Route](https://nextjs.org/docs/api-routes/introduction), otherwise it won't work.
1838

39+
</TabItem>
40+
</Tabs>
41+
1942
#### Parameters
2043

2144
```ts
@@ -26,6 +49,7 @@ function Queue<T>(
2649
): QueueInstance<T>
2750
```
2851

52+
2953
| Parameter | Usage |
3054
| ------------------- | --------------------------------------------------------------- |
3155
| `path` | The route that this queue is reachable at. |

docs/docs/deploying.md

Lines changed: 0 additions & 79 deletions
This file was deleted.

docs/docs/deployment/connecting.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: Connecting your Application
3+
---
4+
5+
To deploy Quirrel, first set up your Quirrel server via [Docker](./docker), [Railway](./railway) or [Fly.io](./fly).
6+
7+
There are three main environment variables you need to specify in your deployment settings:
8+
9+
| Variable | Meaning | Where to get |
10+
| --------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11+
| `QUIRREL_TOKEN` | access token for the Quirrel server. | See "Acquire a token" section below |
12+
| `QUIRREL_BASE_URL` | The base URL of your application's deployment. | You probably know this. Something like `my-application.com`. |
13+
| `QUIRREL_ENCRYPTION_SECRET` | A 32-character-long secret used for end-to-end encryption of your jobs. | Can be generated using `openssl rand -hex 16` or [random.org](https://www.random.org/strings/?num=2&len=16&digits=on&upperalpha=on&loweralpha=on&unique=on&format=html&rnd=new). |
14+
| `QUIRREL_API_URL` | The endpoint your Quirrel Server is running under, e.g. http://your-quirrel-api-address:9181 | |
15+
16+
After setting these variables, you can deploy your application and Quirrel should be working.
17+
If it doesn't, feel free to [reach out](mailto:[email protected]).
18+
19+
:::note Cron Jobs
20+
If you're using [CronJobs()](/api/cronjob), make sure to run `quirrel ci` during the deploy process.
21+
Make sure to have `QUIRREL_API_URL`, a `QUIRREL_TOKEN` and the `QUIRREL_BASE_URL` set when executing `quirrel ci`.
22+
23+
```json
24+
"scripts": { "build": "npm run build && quirrel ci" }
25+
```
26+
27+
:::
28+
29+
:::note VERCEL*URL
30+
If you're on Vercel, you can connect `QUIRREL_BASE_URL` to your `VERCEL_URL`.
31+
Only do this for preview environments, \_not for production*!
32+
`QUIRREL_BASE_URL` is used to determine the deployment that your jobs should be executed on.
33+
If you set it to `VERCEL_URL`, that means all jobs will be executed on the exact deployment that they were
34+
created on, excluding them from future bugfixes.
35+
To connect `QUIRREL_BASE_URL` to `VERCEL_URL`, set its value to `@VERCEL_URL` ([notice the @](https://github.com/quirrel-dev/quirrel/blob/d268f0555211afb202c3c3b12b460d14f0f0fb86/quirrel/src/client/config.ts#L12)).
36+
:::
37+
38+
### Acquire a token
39+
40+
You can acquire an authentication token from your Quirrel Server by running this command:
41+
42+
`curl --user ignored:{PASSPHRASE} -X PUT {QUIRREL_SERVER_URL}/tokens/{NAME_OF_TOKEN}`
43+
44+
> The fields inside of `{}` are placeholders and should be replaced by you.

docs/docs/deployment/docker.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Docker
2+
3+
To deploy Quirrel using Docker, first set up a Redis instance with persistence turned on. Then follow these steps:
4+
5+
1. Pull the official Quirrel Docker image:
6+
7+
```bash
8+
docker pull ghcr.io/quirrel-dev/quirrel:main
9+
```
10+
11+
2. Define your environment variables in a `.env` file:
12+
13+
```env
14+
REDIS_URL=your_redis_url
15+
PASSPHRASES=your_passphrases
16+
REDIS_TLS_CA_BASE64=your_base64_encoded_certificate # if applicable
17+
REDIS_TLS_CA_FILE=your_certificate_file_path # if applicable
18+
```
19+
20+
3. Run the Docker container, replace `<name_of_your_container>` with your preferred container name:
21+
22+
```bash
23+
docker run --env-file .env -p 9181:9181 ghcr.io/quirrel-dev/quirrel:main
24+
```
25+
26+
This will start a new Quirrel container and expose it on port 9181.

docs/docs/deployment/fly.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Fly.io
2+
3+
If you're planning to host your Quirrel instance on Fly.io, you can follow [Mokhtar Mial](https://twitter.com/m5r_m)'s tutorial:
4+
5+
[Self-Hosting Quirrel on Fly.io](https://dev.to/remixtape/self-hosting-quirrel-5af7)

docs/docs/deployment/railway.mdx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Railway
2+
3+
To deploy your own Quirrel server to Railway, click this button:
4+
5+
[![Deploy to Railway](https://railway.app/button.svg)](https://railway.app/new/template/quirrel)
6+
7+
During the process, Railway will clone this repository for you. In there, you find a `Dockerfile`. To pin down your Quirrel version, update its tag:
8+
9+
```diff
10+
- FROM ghcr.io/quirrel-dev/quirrel:main
11+
+ FROM ghcr.io/quirrel-dev/quirrel:sha-f218c98
12+
```
13+
14+
Check Quirrel's [Docker image page](https://github.com/quirrel-dev/quirrel/pkgs/container/quirrel) to find the exact version you want to pin.
15+
16+
Use the `PASSPHRASE` you set during the creation to issue a new token:
17+
18+
```sh
19+
curl --user ignored:<PASSPHRASE> -X PUT https://mighty-owl-production.up.railway.app/tokens/foo
20+
```
21+
22+
You now have your own Quirrel instance 🥳
23+
24+
Next step: [Connecting your application](/deployment/connecting).

docs/docs/development.mdx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Tabs from "@theme/Tabs";
2+
import TabItem from "@theme/TabItem";
3+
4+
# Development
5+
6+
During development, you can use Quirrel's lightweight local server.
7+
This runs entirely on your machine, without needing any database or other external services.
8+
9+
After installing Quirrel via `npm install quirrel`, the local server is started by running `quirrel` in your terminal.
10+
This will start a server and automatically start scanning for CronJobs in your project.
11+
If you're using the default development port of your framework (like `:3000` for Next.js), then Quirrel will automatically detect and use the local server.
12+
13+
You can run `quirrel ui` to open up an admin interface that could be useful in local development.
14+
15+
To always run Quirrel as part of your local development environment, you can add it to your `package.json`:
16+
17+
```json
18+
"scripts": {
19+
"dev": "concurrently 'next dev' 'quirrel'"
20+
}
21+
```

docs/docs/getting-started/next-js.md renamed to docs/docs/getting-started/next-js.mdx

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
---
2-
title: Next.js
3-
---
1+
import Tabs from "@theme/Tabs";
2+
import TabItem from "@theme/TabItem";
3+
4+
# Next.js
45

56
This document guides you through setting up Quirrel and creating your first queue in an existing project.
67

@@ -10,8 +11,8 @@ If you're looking for a tutorial instead, check out the [Water Drinking Reminder
1011

1112
Architecturally, Quirrel consists of two main parts:
1213

13-
1. The Quirrel *server* receives jobs from your application and then makes requests back to it whenever a job is due.
14-
2. The Quirrel *client* is used by your application to interface with the server.
14+
1. The Quirrel _server_ receives jobs from your application and then makes requests back to it whenever a job is due.
15+
2. The Quirrel _client_ is used by your application to interface with the server.
1516

1617
First, we're gonna setup the Quirrel server locally.
1718
To install it, simply run `npm install quirrel` in your project root,
@@ -21,21 +22,44 @@ That's it!
2122
:::note
2223
You can use [`concurrently`](https://github.com/kimmobrunfeldt/concurrently)
2324
to have the Quirrel server be started together with Next:
25+
2426
```json
2527
"scripts": {
2628
"dev": "concurrently 'next dev' 'quirrel'"
2729
}
2830
```
31+
2932
:::
3033

3134
This is all we need installed to create our first Queue!
3235

3336
## Your first Queue
3437

35-
Create a new [API Route](https://nextjs.org/docs/api-routes/introduction) at `pages/api/queues/email.js` and paste the following:
38+
<Tabs>
39+
<TabItem value="app" label="App Router">
3640

37-
```js title="pages/api/queues/email.js"
38-
import { Queue } from "quirrel/next"
41+
Create a new [Router Handler](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) at `app/api/queues/email.js` and paste the following:
42+
43+
```typescript title="app/api/queues/email/route.ts"
44+
import { Queue } from "quirrel/next-app"
45+
46+
export const emailQueue = Queue(
47+
"api/queues/email", // 👈 the route it's reachable on
48+
async job => {
49+
await email.send( ... )
50+
}
51+
)
52+
53+
export const POST = emailQueue
54+
```
55+
56+
</TabItem>
57+
<TabItem value="page" label="Pages Router">
58+
59+
Create a new [API Route](https://nextjs.org/docs/api-routes/introduction) at `pages/api/queues/email.js` and paste the following:
60+
61+
```typescript title="pages/api/queues/email.ts"
62+
import { Queue } from "quirrel/next-pages"
3963

4064
export default Queue(
4165
"api/queues/email", // 👈 the route it's reachable on
@@ -45,6 +69,9 @@ export default Queue(
4569
)
4670
```
4771

72+
</TabItem>
73+
</Tabs>
74+
4875
Up top, we're importing `Queue`, which is a function that we use to declare a new Queue and export it as default.
4976

5077
`Queue` takes two arguments.
@@ -53,10 +80,31 @@ This is required for the Quirrel server to know where jobs need to be sent upon
5380
The second one is a worker function that actually executes the job.
5481
In this example, it sends an email.
5582

56-
5783
Now that we declared the Queue, using it is straight forward.
5884
Simply import it and enqueue a new job:
5985

86+
<Tabs>
87+
<TabItem value="app" label="App Router">
88+
89+
Create a new [Router Handler](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) at `app/api/queues/email.js` and paste the following:
90+
91+
```ts {6-9}
92+
import { emailQueue } from "app/api/queues/email"
93+
94+
// could be some API route / getServerSideProps / ...
95+
export default async (req, res) => {
96+
97+
await emailQueue.enqueue(
98+
..., // job to be enqueued
99+
{ delay: "24h" } // scheduling options
100+
)
101+
102+
}
103+
```
104+
</TabItem>
105+
<TabItem value="page" label="Pages Router">
106+
107+
60108
```ts {6-9}
61109
import EmailQueue from "pages/api/queues/email"
62110

@@ -71,6 +119,9 @@ export default async (req, res) => {
71119
}
72120
```
73121

122+
</TabItem>
123+
</Tabs>
124+
74125
Calling `.enqueue` will trigger a call to the Quirrel server to enqueue a new job.
75126
After 24 hours, when the job is due, the Queue's worker function will receive the job payload and execute it.
76127

@@ -81,4 +132,8 @@ In there, you can also manually invoke jobs, so you don't have to wait for 24 ho
81132

82133
To use it, simply run `quirrel ui` or open [ui.quirrel.dev](https://ui.quirrel.dev) in your browser.
83134

84-
<img src={require("./dev-ui.png").default} alt="Screenshot of the Development UI" height="400rem"/>
135+
<img
136+
src={require("./dev-ui.png").default}
137+
alt="Screenshot of the Development UI"
138+
height="400rem"
139+
/>

0 commit comments

Comments
 (0)