Reference
Options
Set the options under plutoGithub in nuxt.config.ts. Most sites set none. See Defaults.
| Option | Default | Rule |
|---|---|---|
enabled | 'auto' | 'auto', true or false. 'auto' turns the CMS on unless a backend layer is present. See Git CMS. |
storage | 'fs' in development, 'github' in production | 'github' or 'fs'. 'fs' is valid in development only. |
github.repo | Found by Pluto. See Defaults. | owner/name. Required when storage is github. |
github.branch | 'main' | The branch to read and commit to. |
github.appSlug | The env var NUXT_PLUTO_GITHUB_APP_SLUG or PLUTO_GITHUB_APP_SLUG, else '' | The slug of the GitHub App. |
github.apiUrl | 'https://api.github.com' | The API base URL. |
dir | 'content' | A relative path. No .., no leading /, no drive letter. The module changes \ to / and removes a trailing /. |
commit.local | true | In development (storage: 'fs'), commits each save to the local Git repository of the project. Set it to false to only write the files. |
commit.skipDeploy | true | Adds a [skip ci] marker to the commit messages. A site that must redeploy on each edit, such as a docs site, sets it to false. |
cache.headTtl | 60 | Seconds. Zero or more. |
cache.storage | 'cache' | The Nitro storage mount for the cache. |
postType | true | Registers the fixed post content type, on the server and on the client. With false, the admin does not show Posts and does not register the post capabilities. A layer that brings its own types sets it to false. |
A bad option turns the CMS off and logs an error. The module does not throw.
The cache time of the public answers is runtimeConfig.plutoApi.maxAge of core. See Public API.
Defaults
An explicit option always wins over a default.
Storage. In development, the storage is fs. In production, it is github. The env var PLUTO_GITHUB_STORAGE=github makes a development server use GitHub.
Repository. When github.repo is not set, Pluto looks in this order and uses the first match:
- The env var
NUXT_PLUTO_GITHUB_REPO, thenPLUTO_GITHUB_REPO. - The Vercel variables
VERCEL_GIT_REPO_OWNERandVERCEL_GIT_REPO_SLUG. - In development only, the
originremote of the local git repository. Pluto reads.git/configand accepts the https and ssh URLs ofgithub.com. It runs no shell command.
Missing repository. In production, with the storage github and no repository, the module logs one error and the CMS stays off. The build does not fail. Set PLUTO_GITHUB_REPO, or set plutoGithub.github.repo. A nuxt prepare run stays quiet.
A site on Vercel, or a site that runs the dev server in its own git clone, needs no plutoGithub option. A build on another host sets PLUTO_GITHUB_REPO.
Environment variables
The secrets are run-time variables. The module does not check them at build time. Set the secrets as NUXT_PLUTO_GITHUB_<NAME>.
The setup wizard writes these values for you. See Quickstart. To fill them by hand, see GitHub App.
| Variable | Required | Value |
|---|---|---|
PLUTO_GITHUB_REPO | No | owner/name of the repository. Pluto finds it in most cases. See Defaults. |
PLUTO_GITHUB_APP_SLUG | No | The URL name of the GitHub App (github.com/apps/<slug>). |
PLUTO_GITHUB_STORAGE | No | Set to github to test against GitHub in development. |
NUXT_PLUTO_GITHUB_SESSION_PASSWORD | Yes | 32 characters or more, random. |
NUXT_PLUTO_GITHUB_APP_ID | Yes | The App ID. |
NUXT_PLUTO_GITHUB_CLIENT_ID | Yes | The Client ID. |
NUXT_PLUTO_GITHUB_CLIENT_SECRET | Yes | The client secret. |
NUXT_PLUTO_GITHUB_PRIVATE_KEY | Yes | The private key of the App. See Private key formats. |
NUXT_PLUTO_GITHUB_READ_TOKEN | No | A read-only token. It replaces the installation token for anonymous reads. |
NUXT_PLUTO_GITHUB_ALLOWED_USERS | No | GitHub logins, comma-separated, without case. When set, only these users can sign in, even with push access. |
The module puts a non-secret copy of enabled, repo, branch, appSlug, storage, dir, postType, and skipDeploy in runtimeConfig.public.plutoGithub.
Old names
Before version 0.28, the variables had CMS names, such as NUXT_PLUTO_CMS_GITHUB_APP_ID and PLUTO_CMS_REPO. Pluto 0.29 does not read them. Rename them in your host and in .env: NUXT_PLUTO_CMS_GITHUB_<NAME> and NUXT_PLUTO_CMS_<NAME> become NUXT_PLUTO_GITHUB_<NAME>, and PLUTO_CMS_<NAME> becomes PLUTO_GITHUB_<NAME>.
Private key formats
The variable NUXT_PLUTO_GITHUB_PRIVATE_KEY accepts three formats:
- A PEM with real line breaks.
- A PEM on one line, with a literal
\nfor each line break. - The base64 of the PEM, on one line. The value has no
-----BEGINtext. Pluto decodes it and uses the result when it holds a PEM.
The setup wizard writes the base64 format. One line is easy to paste in a host dashboard.
To make the base64 value of a .pem file yourself, run base64 -w0 key.pem.
A minimal config
With the defaults, a site sets only the options that differ:
export default defineNuxtConfig({
extends: ['@plutocms/core'],
plutoGithub: {
github: { branch: 'content' }, // only when the branch is not main
dir: 'docs-content' // only when the folder is not content
}
})
Develop with local Git
In development, the CMS uses storage: 'fs' by default. The dev server reads and writes the local content/ folder, and commits each save to the local Git repository of your project. It never pushes: you push when you are ready.
- One save is one commit, with a message such as
content(post): create "hello". The commit holds only the files of that save. Changes that you staged in other files stay staged. - The commit uses your Git name and email, and runs the hooks of your repository.
create-plutomakes the new project a Git repository with a first commit, so this works on the first save.- Without a Git repository, or without Git, Pluto only writes the files and logs a warning. Run
git initto commit each save. - If a commit fails (for example, a hook stops it), the save is still on disk. The server log says why.
- A local commit has no
[skip ci]marker, so your push deploys as usual. - To only write the files, set
commit.local: false.
Local Git publishing works in development only. storage: 'fs' is an error in a build. On a deployed site, the admin saves only when a GitHub App is connected. See Quickstart.
Open http://localhost:3000/admin. On your machine, you are signed in as a fixed local user with all capabilities. No GitHub step is needed.
The fs store uses the project directory as the root, so a post is at <project>/content/posts/<slug>.md.
x-forwarded-for or forwarded is not local. A request whose Host is not localhost, 127.0.0.1, or [::1] is not local either. A tunnel or a DNS-rebinding page gets no access.Deploy
Deploy to a host with a server runtime, such as Vercel, Netlify, or Node. The site reads the posts at run time, so a static export does not work. See Deploy to Vercel.
Commits
Commit messages have this form. <type> is the name of the content type. For the built-in type, it is post.
content(<type>): create "slug"content(<type>): update "slug"content(<type>): publish "slug"andunpublishcontent(<type>): rename "a" -> "b"content(<type>): delete "slug"
A save that changes nothing makes no commit.
With commit.skipDeploy on, a [skip ci] marker ends the message. A host that honors the marker does not rebuild on each save. Not every host reads this marker. Test it on your host. With skipDeploy on, the edit form shows no build status.
Cache
The store keeps these in a cache:
- The head of the branch, for
cache.headTtlseconds. - The directory index, by
<dir>@<headOid>. - The tree index of a nested type, by head.
- The parsed files, by blob id.
- The rendered HTML and the excerpts, by blob id.
A blob id never changes, so a blob entry never goes stale. The default backend is a Map. With cache.storage, the cache uses a Nitro storage mount.
GitHub Enterprise Server
Set plutoGithub.github.apiUrl to https://<host>/api/v3. The OAuth pages use https://<host>. Any other API URL uses https://github.com.
Rate limits
When GitHub rate limits a call, the CMS answers 503 with a Retry-After header.