diff --git a/archivebox/actors/templates/jobs_dashboard.html b/archivebox/actors/templates/jobs_dashboard.html
new file mode 100644
index 00000000..1af2a897
--- /dev/null
+++ b/archivebox/actors/templates/jobs_dashboard.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Job Dashboard</title>
+    <style>
+        body {
+            font-family: Arial, sans-serif;
+            line-height: 1.6;
+            color: #333;
+            width: 100%;
+            margin: 0 auto;
+            padding: 20px;
+        }
+        h1 {
+            text-align: center;
+        }
+        .dashboard {
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+            gap: 20px;
+        }
+        .card {
+            border: 1px solid #ddd;
+            border-radius: 8px;
+            padding: 15px;
+            background-color: #f9f9f9;
+        }
+        .card h2 {
+            margin-top: 0;
+            border-bottom: 2px solid #ddd;
+            padding-bottom: 10px;
+            font-family: monospace;
+        }
+        .scroll-area {
+            height: 800px;
+            overflow-y: auto;
+            border: 1px solid #ddd;
+            padding: 10px;
+            background-color: #fff;
+        }
+        .job-item {
+            border: 1px solid #eee;
+            border-radius: 4px;
+            padding: 10px;
+            margin-bottom: 10px;
+        }
+        .job-item:last-child {
+            margin-bottom: 0;
+        }
+        .badge {
+            display: inline-block;
+            padding: 3px 7px;
+            border-radius: 3px;
+            font-size: 12px;
+            font-weight: bold;
+        }
+        .badge-started {
+            background-color: #4CAF50;
+            color: white;
+        }
+        .badge-queued {
+            background-color: #2196F3;
+            color: white;
+        }
+        .badge-failed {
+            background-color: #f44336;
+            color: white;
+        }
+        .date {
+            font-size: 16px;
+            color: #666;
+            float: right;
+        }
+    </style>
+</head>
+<body>
+    <h1>Job Dashboard <small><a href="?refresh=true">♻️ {{now}}</a></small></h1>
+    <div id="dashboard" class="dashboard"></div>
+
+    <script>
+        function formatDate(dateString) {
+            // return new Date(dateString).toLocaleString();
+            return new Date(dateString).toISOString().split('T').at(-1).replace('Z', '');
+        }
+
+        function createJobElement(job) {
+            const jobElement = document.createElement('div');
+            jobElement.className = 'job-item';
+            jobElement.innerHTML = `
+                <p><a href="/api/v1/core/any/${job.abid}?api_key={{api_token|default:'NONE PROVIDED BY VIEW'}}"><code>${job.abid}</code></a></p>
+                <p>
+                    <span class="badge badge-${job.status}">${job.status}</span>
+                    <span class="date">♻️ ${formatDate(job.retry_at)}</span>
+                </p>
+                <p style="font-size: 12px; color: #666;">${job.description}</p>
+            `;
+            return jobElement;
+        }
+
+        function updateDashboard(data) {
+            const dashboard = document.getElementById('dashboard');
+            dashboard.innerHTML = '';
+
+            data.forEach(actor => {
+                const card = document.createElement('div');
+                card.className = 'card';
+                card.innerHTML = `
+                    <h2>${actor.model}</h2>
+                    <h3>Queue</h3>
+                    <div class="scroll-area" id="queue-${actor.model}"></div>
+                    <h3>Past Tasks</h3>
+                    <div class="scroll-area" id="past-${actor.model}"></div>
+                `;
+                dashboard.appendChild(card);
+
+                const queueContainer = document.getElementById(`queue-${actor.model}`);
+                actor.queue.forEach(job => {
+                    queueContainer.appendChild(createJobElement(job));
+                });
+
+                const pastContainer = document.getElementById(`past-${actor.model}`);
+                actor.past.forEach(job => {
+                    pastContainer.appendChild(createJobElement(job));
+                });
+            });
+        }
+
+        function fetchData() {
+            fetch('/api/v1/jobs/actors', {
+                headers: {
+                    'Authorization': `Bearer {{api_token|default:'NONE PROVIDED BY VIEW'}}`
+                }
+            })
+                .then(response => response.json())
+                .then(data => updateDashboard(data))
+                .catch(error => console.error('Error fetching data:', error));
+        }
+
+        fetchData();
+
+        setInterval(fetchData, 1000);
+    </script>
+</body>
+</html>
diff --git a/archivebox/actors/views.py b/archivebox/actors/views.py
index 91ea44a2..806d9f25 100644
--- a/archivebox/actors/views.py
+++ b/archivebox/actors/views.py
@@ -1,3 +1,20 @@
-from django.shortcuts import render
 
-# Create your views here.
+from django.views.generic import TemplateView
+from django.contrib.auth.mixins import UserPassesTestMixin
+from django.utils import timezone
+from api.auth import get_or_create_api_token
+
+
+class JobsDashboardView(UserPassesTestMixin, TemplateView):
+    template_name = "jobs_dashboard.html"
+
+
+    def test_func(self):
+        return self.request.user and self.request.user.is_superuser
+
+    def get_context_data(self, **kwargs):
+        api_token = get_or_create_api_token(self.request.user)
+        context = super().get_context_data(**kwargs)
+        context['api_token'] = api_token.token if api_token else 'UNABLE TO GENERATE API TOKEN'
+        context['now'] = timezone.now().strftime("%H:%M:%S")
+        return context
diff --git a/archivebox/core/urls.py b/archivebox/core/urls.py
index 6143e566..00b33e30 100644
--- a/archivebox/core/urls.py
+++ b/archivebox/core/urls.py
@@ -10,6 +10,8 @@ from archivebox.misc.serve_static import serve_static
 from core.admin_site import archivebox_admin
 from core.views import HomepageView, SnapshotView, PublicIndexView, AddView, HealthCheckView
 
+from actors.views import JobsDashboardView
+
 # GLOBAL_CONTEXT doesn't work as-is, disabled for now: https://github.com/ArchiveBox/ArchiveBox/discussions/1306
 # from archivebox.config import VERSION, VERSIONS_AVAILABLE, CAN_UPGRADE
 # GLOBAL_CONTEXT = {'VERSION': VERSION, 'VERSIONS_AVAILABLE': VERSIONS_AVAILABLE, 'CAN_UPGRADE': CAN_UPGRADE}
@@ -21,30 +23,30 @@ urlpatterns = [
     re_path(r"^static/(?P<path>.*)$", serve_static),
     # re_path(r"^media/(?P<path>.*)$", static.serve, {"document_root": settings.MEDIA_ROOT}),
 
+    path('health/', HealthCheckView.as_view(), name='healthcheck'),
+    path('error/', lambda *_: 1/0),                                             # type: ignore
     path('robots.txt', static.serve, {'document_root': settings.STATICFILES_DIRS[0], 'path': 'robots.txt'}),
     path('favicon.ico', static.serve, {'document_root': settings.STATICFILES_DIRS[0], 'path': 'favicon.ico'}),
 
-    path('docs/', RedirectView.as_view(url='https://github.com/ArchiveBox/ArchiveBox/wiki'), name='Docs'),
-
-    path('public/', PublicIndexView.as_view(), name='public-index'),
-    
-    path('archive/', RedirectView.as_view(url='/')),
-    path('archive/<path:path>', SnapshotView.as_view(), name='Snapshot'),
-
-    path('admin/core/snapshot/add/', RedirectView.as_view(url='/add/')),
-    path('add/', AddView.as_view(), name='add'),
-
     path('accounts/login/', RedirectView.as_view(url='/admin/login/')),
     path('accounts/logout/', RedirectView.as_view(url='/admin/logout/')),
 
-
+    path('admin/core/snapshot/add/', RedirectView.as_view(url='/add/')),
+    path('docs/', RedirectView.as_view(url='https://github.com/ArchiveBox/ArchiveBox/wiki'), name='Docs'),
+    path('archive/', RedirectView.as_view(url='/')),
+    
     path('accounts/', include('django.contrib.auth.urls')),
     path('admin/', archivebox_admin.urls),
-    
     path("api/",      include('api.urls'), name='api'),
 
-    path('health/', HealthCheckView.as_view(), name='healthcheck'),
-    path('error/', lambda *_: 1/0),                                             # type: ignore
+    path('public/', PublicIndexView.as_view(), name='public-index'),
+    
+    path('archive/<path:path>', SnapshotView.as_view(), name='Snapshot'),
+
+    path('add/', AddView.as_view(), name='add'),
+    
+    path("jobs/",     JobsDashboardView.as_view(), name='jobs_dashboard'),
+
 
     # path('jet_api/', include('jet_django.urls')),  Enable to use https://www.jetadmin.io/integrations/django