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

@zarx/strapi-plugin-cron-job-manager

v0.0.1-alpha.2

Published

A cron job manager for Strapi

Readme

Strapi Plugin Cron Job Manager

A comprehensive cron job management plugin for Strapi v5 that provides a full-featured admin UI for managing, monitoring, and controlling your scheduled tasks.

⚠️ Development Notice: This plugin is currently in active development and not yet stable. Breaking changes may occur between versions until released. Use with caution in production environments.

Features

  • 📅 Cron Job Scheduling - Define scheduled tasks using cron expressions
  • 🎯 Manual Jobs - Create on-demand tasks that run only when triggered
  • 🎛️ Admin UI Dashboard - View all jobs, enable/disable, trigger manually, and monitor execution
  • 📊 Execution Logging - Detailed logs for every job execution with timestamps and status
  • 🔄 Hot Reload Support - Job metadata updates automatically sync to the database
  • 🗑️ Orphaned Job Cleanup - Delete unregistered jobs and all associated logs through the UI
  • 🏷️ Rich Metadata - Add display names, descriptions, and tags to organize your jobs
  • 🌍 Timezone Support - Configure timezone for each scheduled job
  • 📈 Statistics - Track total jobs, active/inactive counts, and recent executions

Installation

# npm
npm install @zarx/strapi-plugin-cron-job-manager

# yarn
yarn add @zarx/strapi-plugin-cron-job-manager

# pnpm
pnpm add @zarx/strapi-plugin-cron-job-manager

Configuration

1. Enable the Plugin

In your Strapi project's config/plugins.ts (or config/plugins.js):

export default {
  'cron-job-manager': {
    enabled: true,
  },
};

2. Define Your Cron Tasks

Create a file to define your cron tasks (e.g., config/cron-tasks.ts):

import { Core } from "@strapi/strapi";
import { taskHandler } from "@zarx/strapi-plugin-cron-job-manager/strapi-server";

export default {
  // Scheduled job example
  dailyCleanup: {
    task: taskHandler({
      taskName: "dailyCleanup",
      fn: async ({ strapi, executionLog }) => {
        await executionLog.info("Starting daily cleanup");
        
        // Your task logic here
        const result = await strapi.db.query('api::post.post').deleteMany({
          where: { publishedAt: { $null: true } }
        });
        
        await executionLog.info(`Deleted ${result} unpublished posts`);
        
        return {
          message: "Cleanup completed",
          deletedCount: result,
        };
      },
    }),
    options: {
      rule: "0 2 * * *", // Every day at 2 AM
      tz: "America/New_York",
      meta: {
        displayName: "Daily Cleanup",
        description: "Removes unpublished posts older than 7 days",
        tags: ["maintenance", "cleanup", "daily"],
        enabled: true,
      },
    },
  },
  
  // Manual job example
  generateReport: {
    task: taskHandler({
      taskName: "generateReport",
      fn: async ({ strapi, executionLog }) => {
        await executionLog.info("Generating monthly report...");
        
        // Your task logic here
        const report = await generateMonthlyReport(strapi);
        
        await executionLog.success("Report generated successfully");
        
        return {
          message: "Report generation completed",
          reportUrl: report.url,
        };
      },
    }),
    options: {
      // No 'rule' = manual job (only runs when triggered)
      meta: {
        displayName: "Generate Monthly Report",
        description: "Manual job to generate comprehensive monthly analytics report",
        tags: ["report", "manual", "analytics"],
        enabled: true,
      },
    },
  },
};

3. Register Tasks in Server Config

In your config/server.ts (or config/server.js):

import cronTasks from './cron-tasks';

export default ({ env }) => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  // ... other server config
  cron: {
    enabled: true,
    tasks: cronTasks,
  },
});

API Reference

taskHandler(config)

Wraps your task function to provide execution logging and error handling.

Parameters:

  • taskName (string) - Unique identifier for the task
  • fn (function) - Async function containing your task logic

Function Parameters:

  • strapi - Strapi instance for accessing services, queries, etc.
  • executionLog - Logging interface for the current execution

Execution Log Methods:

  • executionLog.info(message) - Log informational message
  • executionLog.success(message) - Log success message
  • executionLog.warning(message) - Log warning message
  • executionLog.error(message) - Log error message

Job Options

options.rule (string, optional)

Cron expression for scheduled jobs. If omitted, the job becomes a manual job that only runs when triggered.

Common cron patterns:

  • "0 0 * * *" - Daily at midnight
  • "*/5 * * * *" - Every 5 minutes
  • "0 */4 * * *" - Every 4 hours
  • "0 9 * * 1" - Every Monday at 9 AM
  • "0 0 1 * *" - First day of every month

Use crontab.guru to build cron expressions.

options.tz (string, optional)

Timezone for the scheduled job (e.g., "UTC", "America/New_York", "Europe/London").

options.meta (object, optional)

Metadata for the admin UI:

  • displayName (string) - Human-readable name shown in the UI
  • description (string) - Detailed description of what the job does
  • tags (string[]) - Array of tags for organization
  • enabled (boolean) - Default enabled state (only applies on first registration)

Important: The enabled state is only used when a job is first registered. After that, the enabled/disabled state is managed through the admin UI and persists across server restarts. Changing meta.enabled in code will not override the user's toggle state.

Admin UI Features

The plugin adds a "Cron Job Manager" section to your Strapi admin panel:

Dashboard View

  • Statistics Cards - Overview of total jobs, active/inactive counts, recent executions
  • Jobs Table - Complete list of all registered and unregistered jobs
    • View job status (Active/Inactive, Scheduled/Manual, Registered/Unregistered)
    • Enable/disable jobs with a toggle switch
    • Trigger manual execution
    • Delete unregistered jobs (with cascading log deletion)
    • Click job name to view details

Job Detail View

  • Job Information - Display name, description, schedule, timezone, tags
  • Execution Logs - Paginated history of all executions with:
    • Execution date/time
    • Status (Success/Failed)
    • Duration
    • Result data
    • Detailed logs with timestamps

Deleting Orphaned Jobs

When you remove a job from your code but it still exists in the database:

  1. The job appears as "Unregistered" in the jobs table
  2. Click the delete icon (🗑️) for that job
  3. Confirm deletion in the modal dialog
  4. The job and all associated logs are permanently deleted

This helps keep your database clean when refactoring or removing old tasks.

Complete Example

Here's a complete example showing scheduled and manual jobs:

// config/cron-tasks.ts
import { Core } from "@strapi/strapi";
import { taskHandler } from "@zarx/strapi-plugin-cron-job-manager/strapi-server";

export default {
  // Scheduled: runs automatically every 5 minutes
  everyFiveMinutesJob: {
    task: taskHandler({
      taskName: "everyFiveMinutesJob",
      fn: async ({ strapi, executionLog }) => {
        await executionLog.info("Scheduled 5-minute sample job started");
        strapi.log.info("Scheduled 5-minute sample job executed");

        return {
          message: "Scheduled 5-minute sample job completed",
          executedAt: new Date().toISOString(),
        };
      },
    }),
    options: {
      rule: "*/5 * * * *",
      tz: "UTC",
      meta: {
        displayName: "Every 5 Minutes Job",
        description: "Sample scheduled job that runs every 5 minutes",
        tags: ["sample", "scheduled", "5m"],
        enabled: true,
      },
    },
  },

  // Manual: only runs when triggered from admin UI
  manualHealthCheck: {
    task: taskHandler({
      taskName: "manualHealthCheck",
      fn: async ({ executionLog }) => {
        await executionLog.info("Manual health check started");

        return {
          message: "Manual health check completed",
          checkedAt: new Date().toISOString(),
        };
      },
    }),
    options: {
      // No 'rule' means manual-only
      meta: {
        displayName: "Manual Health Check",
        description: "Example manual job. No options.rule means it only runs when triggered manually.",
        tags: ["manual", "healthcheck"],
        enabled: true,
      },
    },
  },

  // Scheduled but disabled by default
  inactiveDeleteTestJob: {
    task: taskHandler({
      taskName: "inactiveDeleteTestJob",
      fn: async ({ strapi, executionLog }) => {
        await executionLog.info("Inactive delete-test job executed manually");
        strapi.log.info("Inactive delete-test job executed manually");

        return {
          message: "Inactive delete-test job completed",
          executedAt: new Date().toISOString(),
        };
      },
    }),
    options: {
      rule: "0 0 * * *",
      tz: "UTC",
      meta: {
        displayName: "Inactive Delete Test Job",
        description: "Disabled test job used to verify inactive job handling and deletion workflows.",
        tags: ["sample", "inactive", "delete-test"],
        enabled: false, // Starts disabled
      },
    },
  },
};

Development

Building the Plugin

yarn build

Development Mode with Hot Reload

yarn dev
# or
yarn watch:link

Testing in Playground

# Install plugin in playground
yarn playground:install

# Start playground in dev mode
yarn playground:develop

Requirements

  • Strapi v5.37.1 or higher
  • Node.js 18+ or 20+

License

MIT

Author

Johan Boström [email protected]

Issues & Contributions