# Dashboard and maintenance

**For administrators.** The admin Dashboard — an at-a-glance answer to "what's in Kartotek?" and "what needs attention?" — and the shared design every corpus-wide repair/enrichment task on the site follows. See [Administrator quick start](/_docs/admin-quickstart) for where this sits among the rest of Admin.

## Dashboard

Logging in lands on the Dashboard, organized into six groups. Every number is itself a link into the relevant part of Admin, opening pre-filtered where that's meaningful (for example, the PrePub Posts tile opens the Posts list already filtered to PrePub). If one group's own data can't be loaded for any reason, that group alone shows as unavailable — the rest of the Dashboard still renders normally.

- **Needs attention** — PrePub Posts; the same translation-issue tiles the Translations dashboard itself shows (Failed, Stale, Missing per language, Awaiting review per language — see [Languages and translations](/_docs/translations), each its own separate tile here too, hidden individually when its count is zero); backup issues (a run that failed, or one overdue — see [Backup and disaster recovery](/_docs/backups)); unresolved import issues; and **Rotten links** (distinct current Links whose live destination is currently Missing, with a separate note for how many of those have no preserved copy at all — see [Links and web preservation](/_docs/links)). When every "Needs attention" count is genuinely zero, the whole group collapses into a single **No current issues** note instead of a wall of zeroes.
- **Backfill health** — how many of the corpus's required, ongoing operations (translations, archival, thumbnails, Archive Media scanning/processing, link checks, Dropbox cleanup) have never completed successfully, and the oldest last-successful-completion among the rest, with the most urgent named underneath. Optional or one-time operations (Visual classification, the one-off migration tools, GUI placeholder audit) don't count toward either number just for never having completed — that's expected for them — but any of them currently needing attention still turns the tile red and is named at the top of the list. Red whenever a required operation has never completed, the oldest such completion is more than 14 days old (exactly 14 days doesn't count as overdue), or an optional/one-time operation is currently needing attention; a neutral "No backfill jobs configured" state only if nothing is registered at all — this group is otherwise always shown, healthy or not. Every tile and job name links down to Backfill operations. A job that's been retired from the codebase stops counting here without losing its past history.
- **Content** — Published Posts, Hidden Posts, Categories, Tags, Content Elements, Versions, and Posts with HTML content (see [Text](/_docs/content-text) for what "HTML content" means) — always shown, including at zero. These counts are installation-wide rather than following the domain selector below, since Posts/Categories/Tags aren't owned by any one Domain in the first place — see [Domains, UIDs and addresses](/_docs/addressing). Categories, Content Elements, and Versions are plain counts for now; there's no cross-Post browsing view for any of the three yet, so those three tiles aren't clickable.
- **Activity and data** — visits (today and over the last 30 days; a domain selector at the top of the page scopes this count to one Domain, "All domains," or unconfigured traffic — see [Privacy and analytics](/_docs/privacy)), and the five most recently changed Posts.
- **Operations** — the last successful backup and how long ago that was, current Translation usage, and the most recent JSON import's status. Like Content, these are installation-wide values, not scoped to one Domain.
- **Link evidence** — total Links; how many are Queued/Partial/Complete/Failed overall; coverage counts for each evidence type (live status, PDF, WARC, Wayback, other Web Archive providers); the most recent successful verification across the whole corpus; and, only when nonzero, actionable provider errors and local artifacts awaiting review. Every tile opens the Link evidence matrix pre-filtered — see [Links and web preservation](/_docs/links).

The bar at the top of every admin page shows **Deployed** (when the running version of the site was deployed) and **Updated** — the most recent durable change to the site's database, of any kind: publishing or editing a Post, a Category/Tag/Domain change, a translation landing, a media or link operation, a settings change, or a backfill writing results. Visit-analytics collection deliberately never moves this timestamp — **Updated** answers "when did the site's actual data last change," not "when was it last visited."

## Backfill operations

Below the six groups, the Dashboard carries the site's one **Backfill operations** section — every corpus-wide repair and enrichment task, each as a compact row in one shared design, rather than scattered controls on individual feature pages (those pages link back here instead). Each row shows the operation's name and purpose, what it's actually scoped to right now (a short description of what's covered, plus either **Discovering — N found so far** while that scope is still being assembled, or **Scope: N {items}** once it's fixed and known in full — a handful of one-time audits/migrations are the only operations that ever reach a fixed scope; every ongoing operation stays "Discovering" indefinitely, since its own eligible set is continuously re-evaluated rather than counted once and closed), its current state, **Latest execution** and **Last fully satisfied** (two separate, explicit dates — a failed, cancelled, paused, or dry-run attempt never overwrites an earlier real success; "Never" means exactly that, not merely "not shown in this browser session"), a real n-of-total percentage for the few one-time bounded operations that have one (Dropbox backup cleanup's own scan), or current-state counts (outstanding/completed/skipped/failed/cancelled) for every ongoing operation, since an ongoing operation's own scope never has a fixed total a percentage could honestly represent, and the actions its state allows — Start, Pause, Resume, and (where the operation supports it) Retry failed or a dry run. A nonzero completed/skipped/failed/cancelled count is itself clickable: it expands into why, grouped by reason, and the actual items behind any one reason — no need to leave the Dashboard to see what's actually wrong. An operation that can't run right now says why, right on its row. A **Details** toggle expands whatever further per-operation specifics that row has (a Scope choice, an error summary) without making the summary rows any less dense. Starting anything with real cost (external translation-provider calls, capture work, deletion) asks for confirmation first.

![The Backfill operations section, sorted by name, with each row's own current state](/_docs/images/backfill-operations-normal-desktop-linux.png)

Rows are listed flat, sorted alphabetically by name — never grouped or reordered by an operation's own current state. An earlier design grouped rows by state, moving one into a separate "Needs attention" section the moment it needed attention and back out once resolved; each move unmounted and remounted the row, which surfaced in production as rows visibly jumping position, sometimes repeatedly, while nothing an admin was doing had changed. A row's own state is still shown on the row itself (see "state" below) — it simply never decides where in the page that row lives, which is what makes its position stable across every refresh.

![An operation that needs attention, expanded to show the reasons behind its counts](/_docs/images/backfill-operations-needs-attention-desktop-linux.png)

A **"What do these states mean?"** disclosure above the operations list gives the definition of every state a count can be in:

- **Pending** — discovered and eligible, not yet scheduled for processing.
- **Queued** — scheduled and waiting for a worker to pick it up.
- **Running** — actively being processed right now.
- **Waiting to retry** — a previous attempt failed transiently; waiting out a bounded backoff before trying again.
- **Completed** — the required result was produced or verified — including "already satisfied, nothing to do," which is a real completed outcome, not a skip.
- **Skipped** — deliberately excluded for a recorded reason (wrong type, no longer eligible, a manual override in place) — never a generic stand-in for "unchanged" or "failed."
- **Failed** — a genuine processing attempt errored and needs attention or a retry.
- **Cancelled** — excluded because the run itself was explicitly cancelled — not an error, and never retried automatically.

An operation's own current **state** is a separate concept from an item's state above — it describes the run as a whole: Idle, Discovering, Queued, Running, Pausing, Paused, Finished, **Finished with exclusions** (a run that completed but has at least one Skipped item — worth a look, not a failure), **Needs attention** (an unresolved Failed item remains), Cancelled. Three operations — Media probes, Video thumbnails, and Archive Media content-hash matching — show **Legacy result — item accounting unavailable** instead of "Finished with exclusions" for the same underlying outcome: these were deliberately never migrated onto the per-item tracking every other operation's clickable counts rely on, so there's no per-item breakdown a click here could ever reveal.

**Every resumable operation keeps its checkpoint on the server, in the database** — pausing, reloading the page, or even a deploy landing mid-run never loses progress; Resume continues from exactly where the run left off. Running any of them repeatedly is always safe — an already-complete item is a fast no-op, never duplicated work. **Every operation's execution history — including the six that used to report only from browser memory (GUI translation fill, GUI placeholder audit, Image EXIF metadata, Media probes, Video thumbnails, Archive Media content-hash matching) — is now recorded durably in the database**, keyed by a stable identity independent of the row's own display name, so Latest execution/Last fully satisfied survive a page reload, an application restart, or a Render redeploy just as reliably as an operation's own resumable checkpoint does. A dry run is recorded (so its own row still shows a latest attempt) but never counts as a successful completion. The operations:

- **Post & Content translations**, **Tag translations**, **GUI translation fill**, and **GUI placeholder audit** — see [Languages and translations](/_docs/translations)'s "Backfill relationship."
- **Link health checks** and **Link evidence discovery** — see [Links and web preservation](/_docs/links).
- **Post WARC & Wayback archival** — generates any missing Post WARC capture and submits every associated-Domain URL to the Wayback Machine, described alongside the rest of archival in [Links and web preservation](/_docs/links).
- **Image EXIF metadata**, **Media probes**, and **Video thumbnails** — idempotent catch-up passes over already-ingested media (the two media passes offer a dry run that reports scope without writing anything) — see [Media and the Media Archive](/_docs/media).
- **Archive Media content-hash matching** — gives pre-existing Archive Media items a real content checksum so Kartotek can recognize when the same photo has also been uploaded as Post Media, powering the "Already used in a Post" note on an Archive Media item's detail panel (see [Media and the Media Archive](/_docs/media)). Only items that already look like a likely match are actually downloaded and verified, so this never means downloading your whole archive; dry run reports scope, and each Run processes a bounded batch — click it again to keep making progress.
- **Missing thumbnails** and **Failed EXIF extraction** — the two backfills behind Post Media's and Archive Media's own health metrics, each with its own Scope choice (Post Media, Archive Media, or both) under Details, and dry run/apply. Missing thumbnails targets only currently-missing-thumbnail items via each collection's canonical thumbnail pipeline; Failed EXIF extraction re-attempts only items where an extraction attempt genuinely errored, never a successfully-scanned-no-data or not-yet-attempted item, and also reconciles Video/Audio technical metadata for Post Media. Archive Media items in both are retrieved from Dropbox by each file's own stable identity rather than its last-known path, so a since-renamed, moved, or case-changed file still recovers; a run that finishes with one or more items still unresolved shows **Completed with warnings**, the same distinction Archive Media scan jobs make below, rather than an unqualified Completed that would hide a real remaining failure. See [Media and the Media Archive](/_docs/media)'s "Media health and storage" section.
- **Visual classification** — analyses Images for indoor/outdoor and potentially-identifiable-people signals, entirely locally, across Post Media, Archive Media, or both. Defaults to not-yet-attempted/failed/stale Images; an optional, separately-confirmed setting re-analyses everything, including already-classified Images. Offers dry run/apply, and — because a full-corpus pass can run a while — can also be paused and resumed, or cancelled outright, without losing already-completed work. See [Media and the Media Archive](/_docs/media)'s "Visual classification" section.
- **Archive Media scan** — one row per Archive Root, tracking that root's current or most recent scan/rescan as a resumable job. See "Archive Media scan jobs" below for its states, reasons, and controls in full — Archive Roots itself (see [Media and the Media Archive](/_docs/media)) stays where you add/remove roots; this is where you operate a scan.
- **Archive Media processing** — one row per Archive Root, alongside its scan row, tracking whether every eligible item currently has up-to-date technical metadata, a derivative (display copy), and a content hash. Distinct from the scan row above it: scanning finds what's changed in Dropbox; processing is the separate pass that actually ensures each of those three things for what scanning found. Collapsed, it shows the pipeline's overall state and **Fully processed as of …**; expanded, it breaks that down into its three stages, each with its own clickable counts. Runs entirely on its own — there's nothing to Start or Pause here.
- **Archive Media stage-evidence migration** — one row per Archive Root, alongside its scan and processing rows: a catch-up tool that classifies each pre-existing item's technical-metadata/derivative/content-hash status from evidence already on the row, without reprocessing anything, so items catalogued before Archive Media processing (above) existed get the same real tracking as anything scanned since. Analyse always previews first (a fresh preview is required before Apply is allowed); Apply then migrates the whole root automatically in bounded, resumable batches — no manual "run again to continue," and Pause/Resume/Retry-failed work the same way every other resumable operation's do. Expanded, it breaks progress down into a stage×state matrix (Metadata/Derivative/Hash/Category projection), each cell a clickable count. A fully-migrated root's row stays visible showing Finished, the same as its scan/processing siblings — it never disappears into History.
- **Dropbox backup cleanup** — scans the Dropbox backup destination for temp/journal debris and superseded zero-byte artifacts; actually deleting anything requires a fresh scan's own confirmation token plus an explicit confirmation, and is never automatic — see [Backup and disaster recovery](/_docs/backups).

### Archive Media scan jobs

An Archive Media scan (the initial scan of a newly added root, an ordinary rescan, or an explicit restart) is tracked the same way as every other resumable operation above — a durable, checkpointed job row — but with its own, more detailed set of states and reasons, since a personal Dropbox photo archive can be very large and a scan can span a long time, multiple deploys, and real Dropbox-side rate limiting.

**States**, always exactly one at a time:

- **Queued** — accepted, not yet actively working (reserved for a future queueing mechanism; every scan today moves to Running immediately).
- **Running** — actively listing folders or processing files. A scan waiting out a bounded Dropbox rate-limit/network backoff also shows as Running, with its phase reading "Waiting until …" rather than looking indefinitely stuck — Dropbox rate limiting is a normal, expected, automatically-recovered condition, never treated as a failure or a pause.
- **Pausing** — a Pause was requested; the current page of work finishes first (so a checkpoint is never abandoned mid-page), then it becomes Paused.
- **Paused** — stopped at a safe checkpoint, with a specific reason (below). Resume continues from exactly that checkpoint — never from the beginning.
- **Completed** — a full pass finished with nothing left unresolved.
- **Completed with warnings** — a full pass finished, but at least one item failed or was unsupported; see that job's Issues for what to look at.
- **Failed** — stopped in a way Resume can't cleanly continue from (an unrecognized error, or too many items failing in one run) — investigate, then Restart.
- **Cancelled** — stopped deliberately and terminally, by an admin or because its root was removed; a later Scan begins an entirely new job, not a resume of the cancelled one.

**Reasons**, shown whenever a job is Paused, Failed, or Cancelled: user requested; Dropbox rate limit (only ever shown after the automatic retry budget is exhausted — an in-progress wait is never shown as a "reason," see Running above); Dropbox authorization expired or revoked (reconnect Dropbox, then Resume); a network/transient provider error (also only after retries are exhausted); interrupted by a server restart or deploy; a storage/database error; too many items failed in one run; no progress reported for a while (treated as stalled); the archive root was removed. **A paused job from before this structured-reason system existed shows that explicitly** — "no reason was captured" — rather than guessing one.

**Controls**, all from the Dashboard row: **Pause** (Running only — stops at the next safe checkpoint); **Resume** (Paused only — the same Scan/**Re-check for changes** action Archive Roots itself offers, continuing from the saved checkpoint); **Cancel** (Running/Pausing/Paused — ends it terminally); **Retry failed items** (once nothing is actively running — re-attempts only currently-failed items via Dropbox, without redoing anything that already succeeded); **Discard checkpoint and rescan everything** (once nothing is actively running, with confirmation — an entirely fresh full pass, never resuming the previous job's checkpoint); and a link back to that root's configuration on Archive Roots. The row updates on its own while a scan is active, so there's no separate manual refresh control. A row's **Details** also list per-issue diagnostics (grouped by identical error, with a count and example paths) and a downloadable plain-text diagnostic report suitable for pasting into a bug report — never including any access token, secret, or raw file content.

Progress survives a deploy or a worker restart: a scan resumes from its last durably-saved Dropbox cursor, processing is idempotent (a resumed or retried pass never duplicates a catalogued item, thumbnail, metadata, or Category relationship), and a job that goes silent mid-run (the process died, or it's simply stuck) is automatically detected and made Paused/resumable rather than left looking falsely active forever. That root's own **Last fully satisfied** is drawn from every scan it's ever had, not just the most recent one — a rescan that later fails or gets interrupted never makes an earlier genuine success read back as "Never."

### About the screenshots on this page

The two screenshots above are not hand-captured. They are the same image files the automated visual-regression suite compares every build against, served directly rather than copied. That means they cannot quietly go out of date: if the Dashboard's appearance changes, that suite fails until the image is regenerated, and this page then shows the new one automatically.

## Database Browser

The sidebar's **Admin** tree's **Database** section is a read-only view over the site's underlying SQLite tables and rows — Posts, Categories, Content Elements, Versions, everything, including Hidden content. It's strictly a viewer: there's no way to edit or delete an individual row from here — real changes still go through the normal Post/Category admin flows.

## Storage

`/_admin/storage` (Backup sidebar section → **Storage**) shows live-measured disk consumption for every category Kartotek writes to disk — the live database, uploaded media originals, regenerable caches (Archive Media thumbnails, resized image/video variants), working/scratch space, backup exports, archived Link/Post captures, and Post PDF/JSON exports — each with a plain-language explanation of what it holds. Figures are cached and refreshed automatically in the background; **Refresh now** forces an immediate re-measurement.

Some categories offer a **Clear** action — regenerable caches, working/scratch directories, and confirmed-stale backup-export debris. Clicking it first shows exactly what would be removed (an estimated size and a sample of filenames) before anything is deleted, and requires an explicit acknowledgment. Nothing that holds an original, irreplaceable file (the live database, uploaded media, archived Link/Post captures) is ever offered a Clear action here.

## Troubleshooting

- **A Post isn't showing up on its Category's page.** Check its Stage (must be Published) and whether its current Version is marked Hidden — see [Posts and publishing](/_docs/posts).
- **A visitor reports the top navigation looks wrong, or the root address shows unexpected content.** Check the current hostname's Domain configuration (or, if none matches, the Primary Domain) — see [Domains, UIDs and addresses](/_docs/addressing) — a deleted or unpublished landing target/nav entry falls back automatically, but that Domain's own warnings panel will say so.
- **An import is stuck.** Open it under Imports (see [Import, export and external publishing](/_docs/json-import)) — a staged (not finalized) job means at least one media item needs attention; fix, retry, or finalize with it excluded.
- **Analytics numbers look wrong or empty.** Confirm every required setting is filled in under **Admin → Settings** (or its fallback environment variable) — the Analytics page states exactly which are missing — and that the change you're checking happened after analytics was actually enabled; nothing is backfilled retroactively. See [Privacy and analytics](/_docs/privacy).
