Skip to contentSkip to Content
DeploymentDeploy a hosted board

Deploy a hosted board

A hosted board is two pieces: the kanban, static on GitHub Pages, and folio-board-server on Render, which signs people in with GitHub and commits their edits to the board’s branch. One GitHub App does both jobs: people sign in with it, and the server writes the repository as it. Nothing here costs money for an ephemeral GitHub-only service. Durable authorization and SQLite require a paid persistent disk; see Render and Docker. GitHub refresh runs automatically when supported by the App.

GitHub Pages (the kanban) ── Sign in with GitHub ──▶ Render: /auth/login ──▶ GitHub ▲ │ └──────── #board-code=<one-time code> ◀────────────┘ /auth/callback kanban ── Authorization: Bearer <session> ──▶ Render: /v1/… ── commit, push ──▶ board branch

Who gets in

Anyone can sign in and connect their repositories. A selected repository must be authorized for both the person and the App. Push access enables editing; read access opens the board without edits. Each commit carries the signed-in person as its author and the server as its committer. A session lasts 8 hours.

Set it up once

Create the GitHub App

GitHub → Settings → Developer settings → GitHub Apps → New GitHub App.

FieldValue
GitHub App nameAny free name, e.g. folio-board
Homepage URLThe site, e.g. https://owner.github.io/repo/
Redirect URIhttps://<service>.onrender.com/auth/callback
Expire user authorization tokensOn
Request user authorization during installationOff
Webhook → ActiveOff
Repository permissions → ContentsRead and write
Where can it be installedAny account

Metadata: Read-only comes with Contents. Leave every other permission at No access. After creating it, note the Client ID, generate a client secret. Account mode uses each person’s user access token and does not need a private key. An existing App must also allow installation by Any account.

Connect your repositories

The App’s settings → Install App → your account → Only select repositories → the repositories you want to open. Each new user does this for their own account. The screen must list read and write access to code; if it does not, the permission was not saved.

Create the service on Render

Render → New → Blueprint → connect GitHub and this repository. Render reads render.yaml, builds the Dockerfile and proposes the folio-board service on the free plan. Folio Docs comes from its public repository, so the build needs no credentials.

SettingValue
FOLIO_BOARD_MULTI_REPOtrue: each person chooses their own repository
FOLIO_BOARD_GITHUB_APP_SLUGThe App URL slug, folio-board for the deployed App
FOLIO_BOARD_ORIGINThe site’s origin, e.g. https://owner.github.io
FOLIO_BOARD_PUBLIC_URLThe service’s URL, https://<service>.onrender.com
FOLIO_BOARD_GITHUB_CLIENT_IDThe App’s client id
FOLIO_BOARD_GITHUB_CLIENT_SECRETThe App’s client secret
FOLIO_BOARD_SESSION_KEYGenerated by Render; changing it signs everyone out

If Render names the service differently, set FOLIO_BOARD_PUBLIC_URL and the App’s Redirect URI to the URL it gives. Account mode is the default on existing services too; set FOLIO_BOARD_MULTI_REPO=false only for a dedicated single-repository server.

For a dedicated single-repository server, set FOLIO_BOARD_MULTI_REPO=false, set FOLIO_BOARD_REPO, FOLIO_BOARD_REF and FOLIO_BOARD_PATH, and supply the App key or FOLIO_BOARD_GITHUB_TOKEN.

Point the kanban at the server

In the site’s docs.yaml, then rebuild and publish the site:

kanban: api: url: https://<service>.onrender.com

The published board now offers Sign in with GitHub.

Check it

https://<service>.onrender.com/auth/login?return_to=<a page of the site> answers with a redirect to GitHub, and /v1/board without a session answers 401. Sign in with a second GitHub account that cannot access this project’s repository: it must still reach the repository selector. Connect one of that account’s repositories, select its board branch and directory, and open it. A save must reach only the selected repository, under that account’s name. Verify that the second account cannot open the first account’s private repo.

The free plan sleeps

After a while without requests Render stops the service, and the next request waits while it starts. Free services have ephemeral storage; their authorization database disappears on replacement. Use a persistent disk to preserve SQLite boards, API tokens and encrypted credentials across deployments. Expired browser sessions reconnect through GitHub.

When it fails, the log says why

Render → the service → Logs. The server stops at start with one line that names what to fix, and it logs every sign-in GitHub refuses.

The log saysFix
… is not set; a hosted server reads it from the environmentSet the variable it names in Render
neither FOLIO_BOARD_GITHUB_APP_KEY, FOLIO_BOARD_GITHUB_APP_KEY_FILE nor …Add the secret file github-app.pem
the GitHub App private key is not an RSA PEMPaste the whole .pem, both ----- lines included
GitHub refused the App's JWT (401)The client id and the private key are not the same App’s
the GitHub App is not installed on owner/name (404)Install it on that repository, or add it under Repository access
the GitHub App cannot write owner/nameContents: Read and write, then accept the request on the installation
sign-in: GitHub refused it: …The Redirect URI differs from FOLIO_BOARD_PUBLIC_URL/auth/callback, or the client secret is wrong
Repository list is emptyConnect the App to repositories accessible to this GitHub account
A second account cannot authorize or install the AppChange the App installation setting to Any account
Selector never appears after deployRemove FOLIO_BOARD_MULTI_REPO=false in Render, redeploy, and sign in again

In the browser, a kanban that stays read-only gives its reason in the status mark’s tooltip, and a page that never offers the sign-in has no kanban.api in its build.

Persistent container deployments

The current Docker entrypoint runs folio-board-server container, serializing its configuration from environment values. It includes the remote CLI and MCP. The committed Render Blueprint adds a paid persistent disk for SQLite, token hashes and encrypted credentials. Review Render and Docker before applying it to an existing service.