---
title: "GitHub publishing"
url: "https://rigelcms.dev/docs/github-publishing"
description: "Connect a repository, save to the shared drafts branch and review a batch publish."
---

GitHub mode lets a deployed static editor load and save repository content. It uses a GitHub App user session with the editor’s repository permissions, not an installation bot that grants every visitor write access.

## Configure the repository

Keep the site’s existing schema, collections, menus and preview mappings. Add these options to its `rigel()` configuration:

```
backend: "github",
repo: "owner/repository",
repoRoot: "",
branch: "drafts",
publishBranch: "main",
```

Replace `owner/repository` with the repository containing this site’s content. `repoRoot` is empty when the Astro project is at the repository root; use a relative subfolder such as `sites/website` for a nested project. Content folder options remain relative to that project.

## Choose your GitHub connection

GitHub is the only supported sign-in provider for this backend. We provide the Rigel CMS GitHub App and authentication service as the default connection. Using them is optional: you can register your own GitHub App and run a compatible authentication service without approval from Rigel.

The defaults are `authOrigin: "https://auth.rigelcms.dev"` and `appSlug: "rigel-cms"`. To use your own connection, replace both with your service’s HTTPS origin and your GitHub App’s slug:

```
authOrigin: "https://auth.example.com",
appSlug: "your-github-app",
```

Your service must implement Rigel’s editor sign-in flow; an arbitrary OAuth endpoint is not a drop-in replacement. Register your service’s callback URL with your App and install the App on the repositories you want to edit. Never put a client secret or App private key in Astro’s public configuration.

### Custom service contract

RC1 opens `/authorize` on `authOrigin` with the editor’s exact `origin` and a random `nonce`. After validating the authorization flow and exchanging the code on the server, the callback page sends this message from the same popup to the verified editor origin:

```
window.opener.postMessage({
  type: "rigel:auth",
  provider: "github",
  nonce,
  access_token,
  expires_in,
}, editorOrigin);
```

These variables must come from the validated flow, not arbitrary callback query parameters. The editor checks the popup window, gateway origin and matching nonce. `access_token` must be a GitHub App user token with the `ghu_` prefix, and `expires_in` must be a positive integer in seconds, at most `86400`. Configure expiring user tokens on your App. Personal access tokens and GitHub Enterprise hosts are not supported by this RC1 connection.

## Sign in and grant access

1.  Open `/rigel/` and choose Sign in with GitHub. Use HTTPS for a deployed site, or HTTP `localhost` for local development with the provided authenticator. Its editor-origin checks do not accept HTTP `127.0.0.1` or `[::1]`.
2.  In public mode, confirm the exact editor origin in the authenticator, then authorize the App. Restricted gateways can skip confirmation for explicitly allowed origins.
3.  If prompted, choose Install / configure GitHub access and select the intended repository in GitHub. An organization may require its owner’s approval.
4.  Return to the editor and choose Check repository access.

You need repository write access and an App installation that includes the repository. Publishing also needs App Contents and Pull requests read/write permissions. Identity authorization by itself is not repository authorization.

Only approve editor origins you trust. The App’s repository selection does not reduce a user token to the single repository named in an editor’s configuration.

## Save to drafts

Rigel loads current content from the shared workspace branch. If `drafts` does not exist, it creates it from `main`. It does not reset an existing workspace or force-push it.

Save commits the selected content to `drafts`. Everyone using that branch shares the same pending changes; it is not a private draft branch per editor or article. A saved `draft: true` field is separate from the Git branch and only affects publication if the website filters it.

Conflicting remote changes block Save and preserve the in-memory draft. Copy unsaved edits before reloading after a conflict. If a connection fails after a write, Retry save verifies that write before attempting another change. Reconnect when a session expires; signing out and reloading do not preserve unsaved content indefinitely.

RC1 stores the editor’s access token and expiry in browser `localStorage` under `rigelcms.session`, scoped to the authentication origin, repository, branch and App slug. Signing out clears that stored session, but does not revoke the App’s GitHub authorization. Manage App grants through GitHub settings. Use the editor only on a trusted origin and browser.

The provided gateway keeps refresh tokens in its own HttpOnly cookies. RC1 does not automatically refresh a cross-origin editor session; reopen sign-in when the access token expires.

## Review and publish

RC1 includes in-editor publishing. The repository owner must enable squash merging and disable automatic deletion of head branches so the shared drafts branch survives publication. GitHub protections, required checks and required reviews still apply.

1.  Save the content you intend to publish.
2.  Open Publish and inspect the full pending file list. It includes changes outside CMS-managed folders when they are present on the same branch.
3.  If `main` has advanced, use the offered sync step, then reload and review again. A sync updates drafts without publishing; resolve conflicts on GitHub when necessary.
4.  Confirm the reviewed changes. Rigel creates or reuses the `drafts` to `main` pull request and requests a squash merge of the reviewed head.
5.  Check the site’s build and deployment status before treating the website as updated.

Publishing releases the branch as a batch, not just the open page. If either branch changes after review, review again. Blocked checks, reviews, conflicts or changed permissions stop publication rather than bypassing repository rules. Incomplete or unsupported large comparisons must be reviewed and published on GitHub instead of through a partial list in the editor.

If a publish outcome is unconfirmed, inspect the pull request on GitHub or retry verification before starting another publish. A network error does not prove that a merge failed.

## Deployment and media limits

Configure your hosting pipeline to build the publishing branch. Use a separate draft deployment when you want Preview on website to show saved workspace changes before publication. The editor canvas can patch unsaved values into prepared HTML independently of that deployment.

RC1 limits each managed GitHub content file to 1 MiB (`1024 * 1024` bytes). This limit is separate from `maxFileSize`, which controls local media uploads and imports.

GitHub media writes are not implemented in RC1. Add files through your repository workflow and rebuild the media snapshot. Schemas and defaults remain public configuration; never store credentials in content fields.

Documentation

On this page