Custom Tabs

Posit Package Manager lets administrators add custom tabs to a package’s details page by attaching metadata to that package. This is useful for surfacing related documentation, custom dashboards, changelog renderers, or any external resource alongside the package.

Package details tab row showing built-in tabs alongside custom Changelog and Docs tabs added through metadata

How it works

When Package Manager renders a package’s details page, it scans the package’s custom metadata for keys prefixed with tab.. Each matching entry becomes a tab in the row above the package layout:

  • The tab label is derived from the part of the key after tab.. Hyphens and underscores become spaces, and each word is title-cased. So tab.user-guide becomes a tab labeled User Guide, and tab.setup becomes Setup.
  • The tab content comes from the metadata value, which must be an HTTP or HTTPS URL.
Note

Built-in tabs (Overview, Other Versions, History, Changelog) always render first. Custom tabs follow, grouped by type: all Embedded tabs render before any External tabs, regardless of the order their metadata entries were created in.

Embedded vs external tabs

Package Manager decides how to open each tab based on the target URL’s domain:

  • External: URLs whose domain matches a built-in list of sites known to block iframe embedding. The list includes python.org, github.com, wikipedia.org, stackoverflow.com, medium.com, twitter.com, x.com, facebook.com, linkedin.com, and youtube.com. These open in a new browser tab when the user clicks the tab.
  • Embedded: every other URL renders inline inside Package Manager, framed by an iframe.

An “open in new window” icon marks external tabs so users know what to expect before clicking. Embedded tabs include a small info banner explaining that the content is loaded from an external site, and a fallback Open in New Tab button in case the embed fails — for example, if the target site sets X-Frame-Options: DENY or a CSP that blocks framing. The fallback appears after a 10-second timeout if the iframe never loads.

Note

The known-blocker list is a best-effort shortcut to avoid the 10-second timeout on popular sites that we know do not allow embedding. If you point a custom tab at a site that does block embedding but is not on the list, the tab will still work — it will just take 10 seconds to fall back to the Open in New Tab button on first load.

Embedded custom tab showing iframe content with info banner about external embedding and fallback Open in New Tab button

Adding a tab

Custom tabs are configured by administrators through Package Manager’s custom metadata feature. The general shape is:

  • Key: tab.<your-tab-name> — for example, tab.setup, tab.docs, or tab.dashboard.
  • Value: the URL to display.

See the admin guide on Metadata Services for the exact steps and the supported scopes (per-package, per-repository, per-source).

Note

Use descriptive keys — tab.user-guide reads better than tab.x. The key, with hyphens converted to spaces and words title-cased, is the only thing users see as the tab label, so make it count.

Embedding a Package Manager page

Some Package Manager pages have a chrome-less variant designed to be iframed inside a custom tab — they render the page body alone, without the global header, footer, or banners, so they stack cleanly inside the package details layout.

The Setup page, which shows users the install commands and configuration steps for connecting to a repository, has an embedded variant at:

/embed/repos/<repository-name>/setup

To surface it as a custom tab on every package in a repository, set a tab.setup metadata entry at the repository scope with a value like:

https://<your-ppm-host>/embed/repos/my-repo/setup

The tab opens inline as Setup and shows the repository’s setup instructions without leaving the package details page. This is useful for guiding users to a working install configuration directly from any package they land on.

Setup tab embedded inside a package details page, showing chrome-less setup instructions inside the dynamic tab content area

Note

Only Package Manager pages explicitly built with the chrome-less variant work this way today. The Setup page is the main one. External URLs that you do not control still render with their own page chrome.

Reserved tab names

The following tab names are used by Package Manager’s built-in tabs:

  • Overview
  • Other Versions
  • History
  • Changelog

Package Manager accepts custom metadata with these names. A tab.history or tab.changelog entry renders alongside the built-in tab of the same label. We recommend avoiding them anyway, since:

  • The built-in and custom tabs both appear in the tab row with the same label, which is confusing for users.
  • Reserved names are subject to change as Package Manager evolves; a built-in tab with one of these names can replace or override your custom content with no migration path.

Use a distinct name (tab.release-notes, tab.api-history, tab.compatibility) to keep your custom tab safe from collisions.

Back to top