11  Set up your own universe

11.1 Basic steps

Setting up a universe for your R packages involves just a few steps, outlined below. Additional details for each step are provided in the sections that follow.

  1. Create a Git repository named (all lowercase) <your-username>.r-universe.dev on your GitHub account, containing a packages.json file which lists the Git repositories with R packages to include.
    • For an organization at github.com/ropensci the repository is thus github.com/ropensci/ropensci.r-universe.dev;
    • similarly for an user at github.com/jeroen the repository is github.com/jeroen/jeroen.r-universe.dev. More details.
  2. Install the r-universe app on this same GitHub account or organization for which you want to create the universe. Clicking on the app link will lead you to a page that asks “Where do you want to install R-universe?”. More details.
  3. Wait for your packages to start appearing on https://<yourname>.r-universe.dev once they have finished building. More details.
  4. Document how to install packages from R-universe in the docs of your packages. More details.

11.2 Creating your personal R-universe subdomain

Each user gets a private subdomain on R-universe, where you control the content independently. Subdomains are tied to GitHub accounts or organizations with the same name.

11.2.1 Case-sensitivity

Domain names are by definition case-insensitive and lowercased.

11.2.2 How much GitHub is compulsory?

You need a GitHub account to host the repository for your packages.json registry. However, the R packages themselves do not need to be under the same account or even on GitHub. They can be hosted on any public Git server, such as GitLab or a university Git server. A GitHub account is only required for publishing the packages.json registry.

11.3 Populating the packages.json registry file

In order to publish content on R-universe, you need to create a registry file called packages.json, which lists the Git urls containing the R packages you want to include in your universe. The file is formatted as a JSON array with required fields package and url for each entry, for example:

[
    {
        "package": "curl",
        "url": "https://github.com/jeroen/curl"
    },
    {
        "package": "pdftools",
        "url": "https://github.com/ropensci/pdftools"
    },
    {
        "package": "stringdist",
        "url": "https://github.com/markvanderloo/stringdist",
        "subdir": "pkg"
    }
]

11.3.1 Special case of CRAN packages

When browsing the R-universe homepage you may notice that some major universes that contain many CRAN packages do not have a packages.json registry: When the R-universe app is installed on a GitHub account that does not have a proper packages.json file, the build system automatically starts adding all packages from CRAN which are owned by that particular GitHub account. Ownership is determined by the presence of a link to a GitHub repository in the URL or BugReports field of a CRAN package. Our scraper scans all CRAN packages for GitHub links on a daily basis and stores results in the cran-to-git database.

These are effectively auto-generated registries, on which the build system will fall back if the user does not have a personal registry. As soon as the user creates a proper universe registry repository with the packages.json file, this will take precedence, and the build system will automatically switch over.

11.3.1.1 How to prevent a CRAN/BioConductor package from automatically being indexed by R-universe

CRAN and BioConductor packages with a valid Git URL in the description are automatically indexed by R-universe. To prevent this, add a line to the package DESCRIPTION file with: Config/runiverse/noindex: true (Config/ field names are allowed on CRAN). The R-universe scraper runs once per day, so it can take up to 24 hours for the package to be removed from R-universe.

11.3.2 Tracking custom branches or releases

By default, R-universe tracks and builds the default branch for each package Git repository, for instance master or main. It is possible to customize which Git branch or tag to track by adding a branch field to the registry.

The branch field can take the name of any Git reference (either a branch or a tag). You can also set it to a special value "*release" which will automatically lookup the most recent GitHub release, using the same syntax as in remotes. For example:

[
  {
    "package" : "somepackage",
    "url" : "https://github.com/jeroen/somepackage",
    "branch" : "stable"
  }
  {
    "package": "jose",
    "url": "https://github.com/jeroen/jose",
    "branch" : "*release"
  }
]

If you want to use the default Git branch, it is safest to omit the branch field. This way everything will keep working, even if the default branch gets another name at some point in the future.

11.3.3 Hand-written or programmatically created

You can either hand-write this packages.json file, or programmatically create it using the tools of your choice. For example you can generate it in R from a data frame using jsonlite:

df <- data.frame(
    package = c("curl", "pdftools", "stringdist"),
    url = c("https://github.com/jeroen/curl", "https://github.com/ropensci/pdftools", 
        "https://github.com/markvanderloo/stringdist"),
    subdir = c(NA, NA, "pkg")
)
jsonlite::write_json(df, 'packages.json', pretty = TRUE)

The url value must be a public Git url. This is important; our build servers literally call git clone ${url} on each of the entries. The package field must match the name of the R package from the DESCRIPTION file under that url. If the R package does not live in the root of the Git repository, you also need to set the subdir field to the path of the R package root directory.

When creating a new universe, start by adding no more than a few packages. You can easily add more packages later by updating your packages.json file.

To publish your registry, create a Git repository called <yourname>.r-universe.dev on your GitHub account and push your packages.json file. See for example: https://github.com/maelle/maelle.r-universe.dev.

11.4 Installing the GitHub app

Once you pushed your packages.json file to your new universe repository on GitHub, the next step is to install the R-universe GitHub app on your account.

The “Read and write access to commit statuses” will enable R-universe to show commit status updates (green checkmark) to the repositories of your R packages if they are hosted under that GitHub account.

We recommend to install the app for “All repositories” as you might later add more packages to your universe.

Screenshot of the GitHub app showing a check mark for installation on 'All repositories'.

11.5 Waiting for the first build

Once you installed the app, the system will automatically create your personal monorepo under the R-universe organization: https://github.com/r-universe/<yourname>. This is where the system keeps the full history of your packages. The actions tab of your monorepo is also where the building happens.

Screenshot of the actions tab of the r-universe/maelle repository

After a while (usually no more than one hour), packages and articles that have completed building on all platforms will start appearing on your dashboard, and directly become available for installation by users.

Screenshot of the R-universe dashboard for an universe, where icons link back to the build logs on GitHub Actions.

The GitHub app requires very limited permissions, it only requests permission to read and write commit statuses. This means that the R-universe build system can post a green checkmark on your package Git commits, once your package is successfully built and deployed to R-universe. Thereby R-universe serves as a full CI-CD system that shows you if your package build and deploy was successful.

Screenshot of a GitHub repository demonstrating that clicking on the green icon on the latest commit indicates the successful build of the package for R-universe.

11.6 Adding badges and user instructions

Once your packages have appeared on the dashboard, try installing them in R using the instructions from the dashboard page, for example:

# Enable this universe
options(repos = c(
    maelle = 'https://maelle.r-universe.dev',
    CRAN = 'https://cloud.r-project.org'))

# Install some packages
install.packages('tinkr')

Copy these instructions to your package README.md files to assist users. You can also add an R-universe badge to indicate the deployed version:

The badge API is simply /badges/<package> which will yield an SVG image that can directly be embedded into your markdown files, showing the deployed version for the given package:

![r-universe](https://r-lib.r-universe.dev/badges/cpp11)

For example this would produce the following badge:

11.7 Linking to your universe from other websites

Feel free to add a link to your universe from your other online profile (website, social media, GitHub profile README, etc.). You can use a rocket icon as icon.