npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nuxt-queuekit

v2.0.4

Published

Background job queue for Nuxt applications powered by BullMQ and Redis

Downloads

30

Readme

Nuxt Queue

npm version npm downloads License Nuxt

Background job queue for Nuxt applications, powered by BullMQ and Redis.

Table of Contents

What You Get

  • File-based jobs (server/jobs/**) with auto-discovery
  • Separate worker process for background execution
  • Redis-backed queues via BullMQ
  • Real-time progress/status updates
  • Job lifecycle hooks (onCompleted, onFailed)
  • Queue stats + cancel/retry endpoints
  • Full TypeScript support

Quick Start

1. Prerequisite

Run Redis:

docker run -d -p 6379:6379 redis

2. Install

npx nuxi@latest module add nuxt-queuekit

Or manually:

npm install nuxt-queuekit
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-queuekit'],
})

3. Start app + worker

# terminal 1
npm run dev

# terminal 2
npx nuxt-queuekit worker

That is enough to run jobs using default Redis (127.0.0.1:6379).

Core Workflow

Step 1: Define a job

Create a file in server/jobs:

// server/jobs/SendWelcomeEmail.ts
interface WelcomeEmailData {
  userId: string
  email: string
  name: string
}

export default defineJob<WelcomeEmailData>({
  async handle(data) {
    await sendEmail({
      to: data.email,
      subject: 'Welcome!',
      template: 'welcome',
      data: { name: data.name },
    })

    return { success: true }
  },
})

defineJob is auto-imported in job files.

Step 2: Dispatch from server runtime

Use dispatch() in server runtime code (API routes, server plugins, server utilities):

// server/api/register.post.ts
export default defineEventHandler(async (event) => {
  const { email, name } = await readBody(event)
  const user = await createUser({ email, name })

  const { jobId } = await dispatch('SendWelcomeEmail', {
    userId: user.id,
    email: user.email,
    name: user.name,
  })

  return { success: true, jobId }
})

Step 3: Dispatch from client components

Use useQueue() on the client:

<script setup lang="ts">
const queue = useQueue('default')

async function start() {
  const { jobId, progress, status, result, error } = await queue.add('SendWelcomeEmail', {
    userId: '1',
    email: '[email protected]',
    name: 'User',
  })
}
</script>

Organize jobs in folders

Nested files map to dot notation:

server/jobs/
  emails/NewsletterEmail.ts
  media/ProcessImage.ts
await dispatch('emails.NewsletterEmail', { ... })
await dispatch('media.ProcessImage', { ... })

Job options and retries

export default defineJob({
  queue: 'payments',
  options: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 2000 },
  },
  async handle(data) {
    return processPayment(data)
  },
})

Lifecycle hooks

export default defineJob({
  async handle(data, job) {
    await job.updateProgress(50)
    const output = await generateReport(data)
    await job.updateProgress(100)
    return output
  },

  async onCompleted(job, result) {
    await notifyUser(job.data.userId, result)
  },

  async onFailed(job, error) {
    await alertAdmin(job?.data?.userId, error.message)
  },
})

Monitor and Control Jobs

Check one job

const status = await $fetch(`/api/queue/${queueName}/${jobId}`)
// status.state -> waiting | active | completed | failed | delayed

Stream live events (SSE)

const es = new EventSource(`/api/queue/${queueName}/${jobId}/events`)

Cancel waiting/delayed job

await $fetch(`/api/queue/${queueName}/${jobId}/cancel`, { method: 'POST' })

Retry failed job

await $fetch(`/api/queue/${queueName}/${jobId}/retry`, { method: 'POST' })

Queue statistics

const { stats, loading, error, refresh } = useQueueStats('default')
await refresh()

Configuration

Environment variables

NUXT_REDIS_HOST=127.0.0.1
NUXT_REDIS_PORT=6379
NUXT_REDIS_PASSWORD=
NUXT_REDIS_USERNAME=
NUXT_REDIS_DB=0

Module options

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-queuekit'],
  queue: {
    redis: {
      host: process.env.REDIS_HOST || '127.0.0.1',
      port: Number(process.env.REDIS_PORT) || 6379,
      password: process.env.REDIS_PASSWORD,
      username: process.env.REDIS_USERNAME,
      db: Number(process.env.REDIS_DB) || 0,
    },

    // default: server/jobs
    jobsDir: 'server/jobs',

    // optional extra jobs
    jobs: {
      SendNotification: './server/custom-jobs/SendNotification.ts',
    },
  },
})

jobs entries are appended to auto-discovered jobs from jobsDir.

Production

Run web server and workers as separate processes:

npm run build
npm run start
npx nuxt-queuekit worker --concurrency 10

Worker CLI

npx nuxt-queuekit worker [options]

Options:
  --cwd <path>              Working directory (default: current directory)
  --queue <name>            Single queue name (legacy flag)
  --queues <names>          Comma-separated queues in priority order
  --worker <path>           Path to custom worker script
  --concurrency <number>    Concurrent jobs per worker (default: 5)

Examples:

npx nuxt-queuekit worker
npx nuxt-queuekit worker --queue emails --concurrency 10
npx nuxt-queuekit worker --queues critical,default,low --concurrency 5
npx nuxt-queuekit worker --queue processing --worker ./workers/custom.ts

API Reference

defineJob<T, R>(definition)

export default defineJob<{ userId: string }, { ok: true }>({
  queue: 'default',
  options: { attempts: 3 },
  async handle(data, job) {
    await job.updateProgress(100)
    return { ok: true }
  },
  async onCompleted(job, result) {},
  async onFailed(job, error) {},
})

dispatch(jobName, data, options?)

Server runtime helper that creates a job and returns reactive refs:

const { jobId, queueName, progress, status, result, error, refresh, cancel, retry } =
  await dispatch('SendEmail', { to: '[email protected]' })

useQueue(queueName?)

const queue = useQueue('default')
const job = await queue.add('SendEmail', { to: '[email protected]' })

useServerQueue(queueName?)

Returns BullMQ Queue directly (advanced/non-reactive):

const queue = useServerQueue('emails')
await queue.add('send-email', { to: '[email protected]' })

useQueueStats(queueName = 'default')

const { stats, loading, error, refresh } = useQueueStats()
await refresh()

REST endpoints

  • POST /api/queue/add
  • GET /api/queue/:queueName/:jobId
  • GET /api/queue/:queueName/:jobId/events
  • POST /api/queue/:queueName/:jobId/cancel
  • POST /api/queue/:queueName/:jobId/retry
  • GET /api/queue/:queueName/stats

Troubleshooting

Job not registered

  • Ensure file is under configured jobsDir
  • Ensure default export is defineJob({ ... })
  • Restart dev server and worker after adding new files

Worker is running but jobs do not process

  • Confirm Redis is reachable from worker process
  • Confirm queue names match (job.queue vs worker --queue/--queues)

No real-time updates

  • Ensure worker is running (worker publishes events)
  • Check network/proxy supports SSE

License

MIT License