Skip to main content

Cron UI

Balda provides a built-in web dashboard to visualize and monitor your scheduled cron jobs. This feature helps you quickly see all registered cron jobs, their schedules, frequencies, and timezones in a modern, filterable interface.

Peer dependency — The Cron UI requires cronstrue to convert cron expressions into human-readable descriptions. To enable the UI, you must install it:

# with npm
npm install cronstrue

# or with yarn / pnpm / bun
yarn add cronstrue
pnpm add cronstrue
bun add cronstrue

Basic Setup

Enable the Cron UI by calling cronUi() directly before or after your server starts:

import { Server, cronUi } from 'balda';

const server = new Server({
port: 3000,
});

// Register the Cron UI dashboard as a standalone service
await cronUi({ path: '/cron-dashboard' });

await server.listen();

Once enabled, navigate to http://localhost:3000/cron-dashboard to view your cron jobs dashboard.

Features

The Cron UI dashboard provides:

  • Job Overview: Display all registered cron jobs with their names and schedules
  • Human-Readable Schedules: Automatic conversion of cron expressions (e.g., 0 0 * * * → "At 12:00 AM")
  • Search: Filter jobs by name in real-time
  • Frequency Filter: Filter jobs by their execution frequency
  • Timezone Filter: Filter jobs by their configured timezone
  • Live Counter: Shows total jobs and currently visible jobs after filtering
  • Modern UI: Dark-themed, responsive interface with smooth animations

Configuration Options

CronUIOptions

OptionTypeRequiredDescription
pathstringYesThe route path where the dashboard will be accessible

Example

Here's a complete example with multiple cron jobs:

import { Server, cron, CronService, cronUi } from 'balda';

// Define your cron jobs
class BackupCron {
@cron('0 2 * * *', { timezone: 'UTC' })
async dailyBackup() {
console.log('Running daily backup at 2 AM UTC');
// Backup logic here
}
}

class NotificationCron {
@cron('*/5 * * * *')
async checkNotifications() {
console.log('Checking notifications every 5 minutes');
// Notification logic here
}
}

class ReportCron {
@cron('0 9 * * 1', { timezone: 'America/New_York' })
async weeklyReport() {
console.log('Generating weekly report every Monday at 9 AM EST');
// Report logic here
}
}

// Start the server with Cron UI
const server = new Server({
port: 3000,
});

// Import and start cron jobs
await CronService.massiveImportCronJobs(['src/cron/**/*.{ts,js}']);
await CronService.run();

// Register the Cron UI dashboard
await cronUi({ path: '/cron-dashboard' });

await server.listen();

console.log('Server running on http://localhost:3000');
console.log('Cron Dashboard available at http://localhost:3000/cron-dashboard');

Security Considerations

caution

The Cron UI is publicly accessible by default. In production environments, you should protect this route with authentication middleware.

Protecting the Dashboard

Use middleware to add authentication to the Cron UI route:

import { Server, middleware, cronUi } from 'balda';

// Define authentication middleware
class AuthMiddleware {
@middleware()
async checkAuth(req, res, next) {
const apiKey = req.headers['x-api-key'];

if (apiKey !== process.env.ADMIN_API_KEY) {
return res.status(401).json({ error: 'Unauthorized' });
}

next();
}
}

// Apply to server
const server = new Server({
port: 3000,
});

// Register the Cron UI dashboard
await cronUi({ path: '/cron-dashboard' });

// You can add authentication by using a global middleware
// or by defining a custom route handler for your dashboard

Alternatively, you can disable the built-in UI in production and build your own protected endpoint:

import { cronUIInstance } from 'balda';
import { Router } from 'express';

const router = Router();

router.get('/admin/cron', authenticateAdmin, async (req, res) => {
const html = await cronUIInstance.generate();
res.send(html);
});

Troubleshooting

Dashboard shows "No cron jobs configured"

This happens when:

  • No cron jobs have been registered with @cron decorator
  • Cron jobs haven't been imported before the server starts
  • Cron jobs are defined but CronService.run() hasn't been called

Solution: Make sure to import your cron jobs and call CronService.run():

await CronService.massiveImportCronJobs(['src/cron/**/*.{ts,js}']);
await CronService.run();

Error: "cronstrue not installed as a dependency"

The Cron UI requires cronstrue to convert cron expressions to human-readable text.

Solution: Install the peer dependency:

npm install cronstrue

Cron UI path conflicts with existing route

If you have an existing route that conflicts with the Cron UI path, you'll need to choose a different path.

Solution: Use a unique path for the dashboard:

await cronUi({ path: '/admin/cron-jobs' });

API Reference

cronUi(options: CronUIOptions)

Registers the Cron UI dashboard route.

Parameters:

  • options: CronUIOptions - Configuration object with the following properties:
    • path: string - The route path where the dashboard will be accessible (required)

Returns: Promise<void>

Throws:

  • BaldaError if path is not provided or is empty

Example:

import { cronUi } from 'balda';

// Manually register the Cron UI
await cronUi({
path: '/cron-dashboard'
});

cronUIInstance.generate()

Generates the HTML for the Cron UI dashboard. This is useful if you want to create a custom route with authentication.

Returns: Promise<string> - HTML string of the dashboard

Example:

import { cronUIInstance } from 'balda';

const html = await cronUIInstance.generate();
// Use the HTML string as needed