Connect Gallery

Only publishers and administrators can view and publish from the Connect Gallery.

For more information on how publishers use the Gallery, see the Publishing with the Connect Gallery section of the User Guide.

Feed format

The URL of a GalleryFeed must serve a single JSON document, conventionally named extensions.json. A browser fetches this document directly when a publisher opens the Gallery. The URL must therefore be reachable from the browser, and it must permit cross-origin requests.

The feed that Posit publishes is a working reference: extensions.json.

Each entry in a feed describes one piece of content and points at a deployment bundle. Most of the descriptive fields in an entry come from the extension section of that content’s manifest.json. See Extension bundles for what that bundle must contain.

In the tables below, a required field must be present. The Gallery cannot display an entry that omits one.

Top-level fields

Field Type Required Description
extensions array of objects Yes The entries that the Gallery shows.
categories array of objects Yes The categories that group the entries in this feed. The order of the array sets the order of the category tabs.
tags array of strings Yes The tags that entries in this feed can use.
requiredFeatures array of strings Yes The Connect feature names that entries in this feed can declare.

categories, tags, and requiredFeatures are feed-scoped vocabularies. Individual entries reference them instead of defining their own values. The tooling that builds a feed validates each entry against these arrays.

Each object in categories has three required fields:

Field Type Description
id string The identifier that the category field of an entry references.
title string The label of the category tab in the Gallery.
description string A short explanation that appears below the category tab.

Connect merges the categories of every configured feed into one set of tabs. If two feeds use the same category id, Connect keeps the first definition and discards the second.

Connect decides which names are valid in requiredFeatures. It recognizes the following values:

  • API Publishing
  • OAuth Integrations
  • Current User Execution
  • Posit Chronicle

Connect treats any other name as unsatisfied. The card for such an entry offers How to Upgrade instead of Add.

Extension entries

Each object in extensions describes one piece of content:

Field Type Required Description
name string Yes The short identifier of the entry. It must match the extension.name field in the manifest.json of the bundle.
title string Yes The name that the Gallery card shows.
description string Yes The summary that the Gallery card shows.
homepage string Yes A URL with more information, such as the source repository.
latestVersion object Yes The version that the Gallery offers for deployment.
versions array of objects Yes Every available version, ordered newest first. latestVersion repeats the first element.
category string No The id of one of the categories of the feed. An entry without a category appears only under the All tab.
tags array of strings No The tags of this entry. Each value must appear in the top-level tags array.
imgUrl string No The URL of the icon on the Gallery card. Connect shows a default icon when this field is absent.
adminOnly boolean No When true, only administrators see the entry.

The Gallery deploys latestVersion and matches search terms against title, description, and tags. It reads versions as a history and does not offer an older version for deployment.

Connect uses name to link an entry to the content that a publisher already deployed from it. Each name must be unique across every configured feed.

Versions

Each object in versions, and the latestVersion object, describes one release:

Field Type Required Description
version string Yes The version identifier, as a semantic version such as 1.0.3.
released string Yes The release timestamp, in RFC 3339 format, such as 2026-06-12T00:14:55Z.
url string Yes The absolute URL of the deployment bundle. The Connect server downloads this URL, so the server must be able to reach it.
minimumConnectVersion string Yes The oldest Connect version that can run this release, such as 2025.04.0.
requiredFeatures array of strings No The Connect features that this release needs. Each value must appear in the top-level requiredFeatures array.
requiredEnvironment object No The language runtimes that this release needs.

The bundle at url must be a gzip-compressed tar archive that contains the content and its manifest.json. Versions of Connect before 2025.04.0 have no Gallery support. The lowest useful value for minimumConnectVersion is therefore 2025.04.0.

Connect compares minimumConnectVersion against the version of the server. If the server is older, the card offers How to Upgrade instead of Add. Connect applies the same rule to an unsatisfied entry in requiredFeatures or requiredEnvironment.

Each version records these three fields. An entry can therefore raise its minimumConnectVersion, or add a requirement, in a later release without changing an earlier one.

Environment requirements

requiredEnvironment declares the language runtimes that a release needs. Connect recognizes the keys python, r, and quarto. Every key is optional. Each value is an object with a single requires field that holds a PEP 440 version specifier:

{
  "requiredEnvironment": {
    "python": { "requires": ">=3.11" },
    "r": { "requires": "~=4.4" }
  }
}

Connect compares each specifier against the runtimes that the server has available. The Gallery language filter also uses these keys. Connect ignores any other key.

Admin-only extensions

An entry in a feed can set "adminOnly": true so that only administrators see it. A publisher does not see the card for the entry and cannot add the content from the Gallery.

This field only controls what the Gallery displays. It does not prevent a publisher who knows the repository of the content from deploying it directly.

Extension bundles

The url of a version points at a deployment bundle. The bundle holds the content that Connect deploys when a publisher clicks Add. A field reference for the feed is not enough on its own: an entry with a bundle that Connect cannot deploy appears in the Gallery and then fails.

Bundle format

A bundle is a gzip-compressed tar archive of a content directory, including that directory’s manifest.json. It is the same artifact that a publisher uploads to deploy content from a bundle. Use rsconnect or rsconnect-python to generate the manifest.json, then package the directory:

Terminal
tar -czf hello-shiny.tar.gz -C hello-shiny .

Connect reads manifest.json from the top level of the archive. If the archive holds a single directory and nothing else, Connect moves the contents of that directory up one level first. A command such as tar -czf hello-shiny.tar.gz ./hello-shiny therefore also works.

The Connect server downloads the bundle, so the hosting location has three requirements:

  • The url must be absolute.
  • The Connect server must be able to reach the url. The browser of the publisher does not download the bundle.
  • The url must not need authentication. Connect sends an unauthenticated GET request and sends no credentials. Connect follows redirects and needs a 200 response.

The extension block in the manifest

Content for the Gallery declares an extension block in its manifest.json. The tooling that builds a feed copies these fields into the feed entry. See extension in the User Guide for the type of each field.

Manifest field Feed field Required
extension.name name Yes
extension.title title Yes
extension.description description Yes
extension.homepage homepage Yes
extension.version latestVersion.version Yes
extension.minimumConnectVersion latestVersion.minimumConnectVersion Yes
extension.category category No
extension.tags tags No
extension.requiredFeatures latestVersion.requiredFeatures No
extension.imgUrl imgUrl No

Connect reads only name, version, title, and description from the bundle when it deploys the content:

  • It names the content extension-{name}-v{version}.
  • It sets the content title from title.
  • It sets the content description from description.

Connect reads every other field from the feed, not from the bundle. An entry therefore fails to link back to its deployed content if extension.name in the manifest and name in the feed entry differ.

The content name must match the pattern ^[a-zA-Z0-9_.-]{3,64}$. Use only letters, digits, _, ., and - in name and version, and keep extension-{name}-v{version} to 64 characters or fewer. The title must be between 3 and 1024 characters, and the description must be 4096 characters or fewer.

imgUrl must be an absolute, publicly reachable URL. The Gallery uses the value as an image source, so a path relative to a repository does not resolve. The card displays the image at 50 by 50 pixels, so an icon works better than a screenshot.

Other manifest requirements

Connect applies the same rules to a Gallery bundle as to any other bundle. The manifest.json must declare an app mode in metadata.appmode and an entry point, and it must declare the package dependencies of the content. See the manifest reference in the User Guide for these fields.

A deployment also fails if the server prohibits the app mode of the content.

Where environment requirements come from

The requiredEnvironment block of a feed entry mirrors the environment block of the manifest.json. Declare a version specifier for each language that the content uses:

manifest.json
{
  "environment": {
    "python": { "requires": "~=3.11" },
    "r": { "requires": "~=4.4" }
  }
}

Use the ~= compatible-release operator to accept as many installations as possible. ~=4.4 means at least version 4.4 and less than version 5.0.

Connect ignores any key in requiredEnvironment that is not python, r, or quarto. A feed built from a manifest environment block can also carry image and prebuilt keys, which the Gallery ignores.

Node.js content

Node.js content declares its version in the engines.node field of package.json, with npm semver syntax:

package.json
{
  "engines": {
    "node": ">=22"
  }
}

Use an open lower bound such as >=22. An upper bound such as ^22 limits the servers that can run the content. Do not add a nodejs key to the environment block of the manifest, because Connect reads the Node.js version from package.json.

The Gallery cannot check a Node.js version. A nodejs key in requiredEnvironment has no effect on the card. Set minimumConnectVersion to 2026.06.0 or later for Node.js content. Node.js content is generally available from that release. This version check is the only requirement that keeps such an entry off a server that cannot run it.

Node.js hosting also needs NodeJs.Enabled and a license that permits it. See Node.js for the full list of requirements. A feed cannot declare either one, so the deployment fails on a server without them.

How Connect checks requirements

The Gallery checks minimumConnectVersion, requiredFeatures, and requiredEnvironment in the browser, before a publisher clicks Add:

Field What Connect compares it against
minimumConnectVersion The version of the server. Connect compares each dotted number in order.
requiredFeatures The license and the configuration of the server. Connect treats any other name as unsatisfied.
requiredEnvironment The R, Python, and Quarto installations that the server reports.

Under off-host execution, one execution environment must satisfy every key in requiredEnvironment on its own.

If one check fails, the card offers How to Upgrade instead of Add. The dialog behind that button lists each unsatisfied requirement. A failed check never hides a card. Only adminOnly hides one.

These three fields gate the button. They do not gate the API, and Connect does not check them again when it deploys the bundle. The environment block of the manifest.json is different: Connect enforces it when it builds the content, and the build fails when no installation satisfies the specifier.

Failure modes

An entry appears in the Gallery even when its bundle cannot deploy. This is the most common problem for an administrator who hosts a custom feed. The card shows the failure message with a View logs action. The failed content item remains on the server, so the log stays available.

The following problems each produce a failed deployment:

  • The Connect server cannot reach the url, or the url does not return 200.
  • The bundle is not a gzip-compressed tar archive.
  • The archive has no manifest.json at its top level.
  • The manifest.json is not valid JSON, or metadata.appmode holds a value that Connect does not know.
  • The name extension-{name}-v{version} breaks the naming rule.
  • No installed R, Python, or Quarto version satisfies the requires value in the environment block of the manifest. A feed whose requiredEnvironment disagrees with that block passes the card check and then fails the build.
  • The content is Node.js content and the server does not run Node.js.
  • Connect cannot install the packages that the manifest declares.

One more failure affects the whole page. The browser fetches every configured feed together. If one feed URL fails, the Gallery shows an error instead of the entries of the other feeds. Check a new feed URL in a browser before you add it to the configuration.

Example: one extension in a custom feed

This example serves a single Shiny for Python application from a custom feed.

Step 1: prepare the content

The content directory holds the application, its dependencies, and its manifest:

hello-shiny/
├── app.py
├── requirements.txt
└── manifest.json

Generate manifest.json with rsconnect-python:

Terminal
cd hello-shiny
rsconnect write-manifest shiny .

This command writes the metadata, python, and files sections of manifest.json. Add the extension and environment blocks by hand:

hello-shiny/manifest.json
{
  "environment": {
    "python": { "requires": "~=3.11" }
  },
  "extension": {
    "name": "hello-shiny",
    "title": "Hello Shiny",
    "description": "A minimal Shiny for Python application.",
    "homepage": "https://github.com/your-org/your-feed/tree/main/extensions/hello-shiny",
    "category": "example",
    "tags": ["python"],
    "minimumConnectVersion": "2025.04.0",
    "version": "1.0.0"
  }
}

The example above shows only the two blocks that you add. Keep the sections that rsconnect write-manifest wrote.

Step 2: package the bundle

tar -czf hello-shiny.tar.gz -C hello-shiny .

Step 3: host the bundle and the feed

Upload hello-shiny.tar.gz to a location that the Connect server can reach without authentication. Then write the feed and host it at a location that a browser can reach:

extensions.json
{
  "categories": [
    {
      "id": "example",
      "title": "Examples",
      "description": "Pre-built content that illustrates what our team publishes to Connect."
    }
  ],
  "tags": ["python"],
  "requiredFeatures": [],
  "extensions": [
    {
      "name": "hello-shiny",
      "title": "Hello Shiny",
      "description": "A minimal Shiny for Python application.",
      "homepage": "https://github.com/your-org/your-feed/tree/main/extensions/hello-shiny",
      "category": "example",
      "tags": ["python"],
      "latestVersion": {
        "version": "1.0.0",
        "released": "2026-06-12T00:14:55Z",
        "url": "https://artifacts.example.com/gallery/hello-shiny-1.0.0.tar.gz",
        "minimumConnectVersion": "2025.04.0",
        "requiredEnvironment": {
          "python": { "requires": "~=3.11" }
        }
      },
      "versions": [
        {
          "version": "1.0.0",
          "released": "2026-06-12T00:14:55Z",
          "url": "https://artifacts.example.com/gallery/hello-shiny-1.0.0.tar.gz",
          "minimumConnectVersion": "2025.04.0",
          "requiredEnvironment": {
            "python": { "requires": "~=3.11" }
          }
        }
      ]
    }
  ]
}

The entry name matches extension.name in the manifest. The entry category matches the id of the one category, and the entry tags appear in the top-level tags array.

Step 4: configure the feed

/etc/rstudio-connect/rstudio-connect.gcfg
[GalleryFeed "internal"]
URL = "https://feeds.example.com/extensions.json"
Name = "Internal Extensions and Examples"
Description = "Extensions and examples maintained by our team"
Repo = "https://github.com/your-org/your-feed"

This section replaces the default feed. To keep the default feed as well, add it back as shown in Gallery feeds.

Restart Connect to apply the change.

Step 5: check the result

  1. Open the feed URL in a browser. The document must load, and the response must permit cross-origin requests.
  2. Sign in as a publisher and open the Gallery.
  3. Check that the Hello Shiny card appears under the Examples tab, and that it names the feed.
  4. Check that the card footer shows ~=3.11 for Python and 2025.04.0+ for Connect.
  5. Click Add. Connect downloads the bundle and deploys it.
  6. Check that the new content item is named extension-hello-shiny-v1.0.0.

If the card offers How to Upgrade instead of Add, open the dialog. It names the requirement that this server does not satisfy.

If the deployment fails, click View logs on the failure message. The log names the step that failed.

Air-gapped environments

If your Posit Connect server is running in an air-gapped environment, it will not be able to access the Connect Gallery’s content. In this case, it is recommended to disable the feature by setting the Server.GalleryEnabled configuration option to false.

This will prevent the Connect Gallery from making outbound requests, instead showing links to the open source repositories.