Dashboards
docStatic adds dashboard functionality to TinaCMS. Tina generates a GraphQL API using the filesystem in the Git repository as the database. Dashboards query the API (locally or in the cloud) and present actionable reports directly in the CMS. Dashboard functionality is currently considered beta. The functionality is fully tested, but the user interface is provisional and requires refinement. Dashboards update when the page is updated. If another user has made changes since you viewed a dashboard, you can click Refresh to update the dashboard.
Depending on the amount of content in the system, some dashboards may take some time to load. These dashboards will typically update slightly faster when running locally.
Viewing the dashboards
From the CMS, navigate to the Dashboards collection. At the top of the page is a status bar that shows the GraphQL connection. It indicates if you are connected to the cloud or localhost. If the localhost is available, it will always connect to the localhost. To use the cloud, ensure the local dev server is stopped. The status bar also displays the environment and checks all settings are valid.
Viewing workflow status
The Content Overview dashboard show the total number of topics in the /docs path and the topics in each workflow status:
- Draft
- Review
- Translate
- Approved
- Published
- Unlisted
Click the status link to display all topics in that status.
Click Edit to open the topic for editing.
Click the Close icon to close the list of topics.
Viewing recent activity
The Recent Activity section shows recently changed topics. You can filter the time range (All time, Last week or Last month) and set the number of results from 5 to 50.
Viewing translation status
The Translations dashboard shows the status of each topic for the language selected from the list:
- Up to date: The last modified date of the translation is later than the source.
- Outdated: The last modified date of the source is later than the translation.
- Missing: There is a source file with no equivalent translation file.
Viewing content reuse
The Content Reuse dashboard shows the reusable content in the system and where it is used. It reports on four categories:
- Code Snippets: code files referenced by the CodeSnippet component.
- Glossary Terms: terms defined in the glossary terms collection.
- Snippets: MDX content files referenced by the Snippet component.
- Variable Sets: variable sets referenced by the VariableSet component.
Click a category card to see a list of items in that category with the topics where each item is used.
Viewing reuse suggestions
The Suggestions section of the Content Reuse dashboard identifies content that could be converted to reusable components:
- Possible Snippets (code): Inline code blocks in topics that could be extracted into code snippet files.
- Possible Terms: Glossary term text appearing as plain text in topics that could use the GlossaryTerm component instead.
- Possible Snippets (duplicate text): Blocks of text appearing in two or more topics that could be extracted into snippet files.
- Possible Variables: Variable values appearing as plain text in topics that could use the VariableSet component instead.
Click a suggestion card to see the items found and the topics where they appear.
Viewing media reuse
The Media Library dashboard shows where content in the /static/img path is used. It shows the total number of files and images, file size, image paths and image sizes.
You can filter by:
- All content.
- Images only.
- Recent (7 days).
- Used.
- Unused.
For used content, click Used in n docs to display the topics where the content is used. You can then click Edit to edit those topics.
Checking link health
Unlike the other dashboards on this page, the Link Health dashboard lives in the URLs collection rather than Dashboards: it's the same place you manage the centralized URLs used by the <Url> component, so link health and link management sit together.
The dashboard reports on the hyperlinks in your topics and the URLs stored in the URLs collection, including their HTTP status. So a page that returns 404 or 500 is identified as broken no matter which source it came from. The dashboard displays the results of the last yarn check-links run, bundled into the site the last time it was built. To check your links with real HTTP statuses, run:
yarn check-links
This requests every external link — both hardcoded in docs and stored in the URLs collection — records what each server answered, and updates the report. Run it whenever you want fresh results, then rebuild the site so the dashboard picks up the new report. The dashboard shows the date and time of the last check.
Click Refresh on the dashboard to update it without a rebuild. This queries the current docs and URLs collection over GraphQL, so it reflects edits made since the last build—useful in TinaCloud, where there's no shell to run yarn check-links from. It also probes external links directly from your browser, but a browser cannot read the HTTP status of a link to another site the way yarn check-links can, so anything Refresh checks itself is reported as Unverified rather than OK or Broken; it never overwrites a real verdict yarn check-links already recorded for a link that's still present, only fills in what's new or was never checked.
The report counts:
- Total links.
- OK: the server answered with a success or redirect status.
- Broken: the server answered with an error status, such as 404 Not Found or 500 Internal Server Error. These are the links to fix.
- Unverified: no answer came back, so the link could not be judged. Causes include a domain that did not resolve, a request that timed out, a site that refused the request with 403, and rate limiting with 429. Any of these can be a problem with the machine running the check rather than the link, so validate these manually by clicking the hyperlink.
- Internal: links that are not requested. This covers internal links, anchors,
mailto:andtel:links, and localhost addresses. - Files scanned.
- Centralized: how many of the checked links come from the URLs collection rather than being hardcoded in a doc.
- Migration candidates: distinct external URLs that are hardcoded in a doc, not yet present in the URLs collection and worth centralizing—see below for what qualifies.
Internal links are deliberately not requested here, because the site build already validates them against the real page list and reports any that are broken. Localhost addresses are also skipped, since they point at whatever happens to be running on the machine doing the check. You can document a localhost URL without it being reported.
The dashboard lists files with problem links, tagging each one with whether it came from a doc or the URLs collection so you know which one to open. It also lists migration candidates — external URLs used in docs that aren't centralized yet, grouped so a URL repeated across several docs shows once, with a Centralize button that adds it to the URLs collection.
Clicking Centralize adds the entry to the URLs collection form, but not to the dashboard's own view of it. Save the entry—adding any other language URLs it needs—then click Refresh before it moves to Centralized, Not Yet Updated in Docs with a Replace button. That gap is deliberate, not something to work around: Replace shouldn't be offered before the entry actually has the data to replace a hardcoded link with, and filling in the language variants an entry needs can't be automated, since sites are too inconsistent in how they handle them—different path prefixes, different domains, some with no per-language URL at all—for anything but a person to look up and enter.
Centralizing a URL doesn't touch the docs that still hardcode it—that's a separate step, since adding the urls.json entry and swapping every doc reference for it are different edits. The dashboard tracks these separately, under Centralized, Not Yet Updated in Docs, with a Replace button that swaps every hardcoded use of that URL for a <Url> reference in one step, across however many docs it appears in. Each occurrence keeps its own link text—a URL linked with different wording in two different docs gets two different overrides, not one borrowing the other's—unless that wording already matches the key's own default text for that language, in which case Replace leaves the override off and the bare key does the same job without duplicating the same string into every doc that would ever need to change it.
Replace also checks every translation of each doc independently of the English source and updates any that still hardcode the same link—using that translation's own wording, not the source's. A localized <Url> only pays for itself once every language is actually using it, so leaving translations hardcoded would defeat the point of centralizing the link in the first place. A translation that doesn't exist, or doesn't happen to hardcode this particular link, is left untouched.
Not every hardcoded external URL is a migration candidate. Centralizing one only pays for itself when it repeats or carries a language variant, so a URL shows up here only if either is true:
- It's hardcoded in two or more docs.
- Its target has a language variant to carry: either the page itself declares one with
<link rel="alternate" hreflang>, or it's a Wikipedia article, which is a known exception—Wikipedia has language variants but doesn't publish hreflang tags for them.
A single-use link to a page with no detected variant just stays a plain hardcoded link; it's not worth a urls.json entry on its own. A candidate that qualifies only by language variant is labelled has a language variant so it doesn't look like the repeat-count rule was skipped.
Detecting hreflang requires fetching the target page's HTML, which only yarn check-links can do reliably—it runs from Node, so it isn't subject to the browser's cross-origin restrictions. Clicking Refresh also attempts this from your browser, and it works for sites that send permissive CORS headers, but plenty don't; when a site blocks the read, Refresh has no way to tell whether a variant exists and leaves that candidate out until yarn check-links runs. Wikipedia's exception applies either way, since it's decided by hostname rather than a request.
To fail a build when broken links are found, for example in a continuous integration job, run yarn check-links --strict. This exits with an error only for broken links, not unverified ones, so an intermittent network problem does not fail your build.
Related topics
- Hosted CMS – Using docStatic with cloud-hosted or self-hosted TinaCMS.
- Adding the CMS to an iPad home screen – Adding the CMS to an iPad home screen
- CALS Tables – Using CALS tables in docStatic, including merged cells, column widths and border control.
- Citations – Cite sources from a central CSL bibliography.
- Configuration – Configuring your site's behaviour through docusaurus.config.ts and more.
- Create a doc – Create a Markdown document.
- Figures – Images with captions and lightbox zoom.