Configuration
Every option in goodfellow.config.tsx, which both the site and its admin panel import.
A site's goodfellow.config.tsx says which blocks it has and where it's stored. The site's pages and its admin panel import the same file, so the editor always offers exactly the blocks the site renders.
import { blocks, categories } from "@goodfellow-cms/blocks";
import { defineConfig } from "@goodfellow-cms/core";
import { github } from "@goodfellow-cms/github";
import { installedBlocks, installedCategories } from "./blocks/installed";
import { MassTimes } from "./blocks/mass-times";
export default defineConfig({
blocks: { ...blocks, ...installedBlocks, MassTimes },
categories: { ...categories, ...installedCategories, parish: { title: "Parish", components: ["MassTimes"] } },
backend: github({ repo: "your-name/your-site" }),
});Options
| Option | What it does |
|---|---|
blocks |
The blocks the editor offers, keyed by the name content files store. Never rename a key once pages use it. |
categories |
Groups for the editor's block list, as in Puck: { id: { title, components } }. The built-in groups start open where they fit what's edited (OPEN_CATEGORIES in @goodfellow-cms/react); your own start open unless you set defaultExpanded: false. |
backend |
Where the site is stored: github({ … }) or gitlab({ … }). Builds include the admin panel at /admin only when this or demo is set. |
base |
The address the site is served from, for hosts that use a subfolder, such as /my-repo/. Defaults to /. See Commands. |
styles |
The site's stylesheet. Defaults to src/styles.css. |
ai |
The AI assistant: false removes it, { providers: ["anthropic", "manual"] } limits the services offered, and { stockPhotos: false } stops it finding photos on Openverse. |
registries |
Block registries the Blocks screen offers blocks from, besides Goodfellow's: { "@acme": "https://acme.example/r/{name}.json" }. List only registries you trust; see Block registries. |
broker |
The site's token broker, { url: "https://broker.example.org" }, a sign-in page on an address of its own that keeps editors' tokens and AI keys and shows the admin panel in a frame. Site Settings' Security tab writes it. Editors then sign in only there. |
admin |
The admin panel's own address, { url: "https://admin.example.org", checked: true }, which the Domain screen writes (see An admin address). With url, builds start every page with a script that sends it to the Site address when it's opened at the admin address, and fail if a page can't start with it, such as one with a script or an event handler before it; with checked, the admin panel opens only there. Not for full-stack Next.js sites. |
copies |
The addresses of the site's other copies, such as a staging site built from another branch, where the sign-in service signs editors in too: ["https://staging.example.org"]. Each copy is built with its own address and search engine setting; see Staging and production. The live site publishes these addresses in goodfellow-site.json and its admin panel, so anyone can find them. |
claude |
What Claude can do through the Claude connector: { publish: false } stops it publishing, so it can only submit its changes for review. It takes effect once the site has been rebuilt. See Work with Claude. |
demo |
true makes the admin panel a demo anyone can try. |
api |
false leaves the content API, the site's content as JSON at /api/, out of builds. It's on by default. |
plugins |
Plugins, such as [...installedPlugins, s3({ … })], where installedPlugins (from ./plugins/installed) lists those installed from the admin panel, which add screens and code in the admin panel, steps in the build and routes on full-stack sites' servers, as well as blocks, which are added to blocks. Each gets only the permissions it declares, where Goodfellow can enforce them. |
GitHub
github({ repo: "owner/name", branch: "main" })repo: the repository, asowner/name.branch: the branch the live site is built from, and editors publish to. Defaults to the repository's default branch. A staging copy can take it from the environment (see Staging and production).signIn: the address of a sign-in service you run, for Sign in with GitHub. Without it, editors sign in with tokens.contentOnly:truewhere the repository holds only the site's content, with its code in a repository of its own (see Content in a repository of its own).code: withcontentOnly, the code's repository, asowner/name, whose updates the Updates screen follows.apiUrl,webUrl: for GitHub Enterprise.
GitLab
gitlab({ project: "group/site", clientId: "…" })project: the project's path, such asgroup/siteorgroup/subgroup/site.clientId: the Application ID of the site's OAuth application, for one-click Sign in with GitLab. Without it, editors sign in with a token.branch: the branch the live site is built from.contentOnlyandcode: as for GitHub, with the code project's path.url: for self-managed GitLab. Defaults tohttps://gitlab.com.
Bitbucket
bitbucket({ repo: "workspace/site", clientId: "…" })repo: the repository, asworkspace/name.clientId: the Key of the workspace's OAuth consumer, for one-click Sign in with Bitbucket. Without it, editors sign in with a token.branch: the branch the live site is built from.contentOnlyandcode: as for GitHub, with the code repository asworkspace/name.
Bitbucket Cloud only.
AI services
ai.providers takes these ids: anthropic, openai, gemini, groq, mistral, openrouter, ovhcloud, custom (any OpenAI-compatible service) and manual (copying the request into a chat app).