You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Keystatic needs server-side code to handle the GitHub OAuth callback and API requests
(/keystatic/api/* routes). Since the project currently builds as a static site
(no adapter), we need to add an SSR adapter to deploy these routes.
Architectural change
Before
After
Output mode
static (implicit default)
hybrid (most pages static, Keystatic API SSR)
Adapter
None
@astrojs/netlify
Keystatic in production
Excluded
Included
Deploy target
dist/ (static files)
Netlify Functions + static files
Admin UI URL
localhost:4321/keystatic
https://docs.bread.coop/keystatic
Steps
1. Install the Netlify adapter
npx astro add netlify
Or manually:
npm install @astrojs/netlify
This adds the adapter to astro.config.mjs:
importnetlifyfrom'@astrojs/netlify';exportdefaultdefineConfig({output: 'hybrid',// or 'server' — see note belowadapter: netlify(),// ...});
2. Choose output mode
Two approaches:
Option A — output: 'hybrid' (recommended)
Most pages pre-rendered at build time (same as today's static behavior)
Only Keystatic API routes (/keystatic/api/*) run as Netlify Functions
Minimal change to existing page rendering
May need export const prerender = false on any non-API Keystatic page
Option B — output: 'server'
All pages rendered on-demand by default
Must explicitly add export const prerender = true to static pages
More Netlify Function invocations = higher cost/latency
Not recommended unless Option A proves insufficient
Without this, GitHub OAuth will fail in production.
5. Set env vars on Netlify
The four env vars from .env (generated in #11) must be set in the Netlify dashboard
or netlify.toml. The Netlify site manager needs to add:
KEYSTATIC_GITHUB_CLIENT_ID = <value from .env>
KEYSTATIC_GITHUB_CLIENT_SECRET = <value from .env>
KEYSTATIC_SECRET = <value from .env>
PUBLIC_KEYSTATIC_GITHUB_APP_SLUG = <value from .env>
⚠️ Do NOT commit .env to the repo. These are already in .gitignore.
How to set on Netlify:
Netlify dashboard → Site settings → Environment variables → Add variables
Or via CLI: netlify env:set KEYSTATIC_GITHUB_CLIENT_ID "<value>"
6. Update netlify.toml (if needed)
The current netlify.toml is minimal:
[build]
command = "npm run build"publish = "dist"
With the adapter, astro build outputs to both dist/ (static) and .netlify/ (functions). The default publish = "dist" should still work.
No changes expected, but verify after astro build.
7. Build and deploy
npm run build
Verify:
dist/ contains static HTML (as before)
.netlify/functions-internal/ contains Keystatic API function(s)
No build errors
npm run preview works locally (simulates SSR)
Deploy to Netlify (via git push or CLI):
netlify deploy --prod # or push to main for auto-deploy
8. Smoke test the deployed admin UI
Visit https://docs.bread.coop/keystatic
Login with GitHub works (OAuth redirects correctly)
Admin UI loads with collections visible
Create a test entry, save — commit appears on GitHub
Edit an existing page, save — commit appears on GitHub
All static pages still render correctly (/, /about/, etc.)
Redirects still work (/token → /about/bread-token, etc.)
Netlify manager action items
The following must be done by someone with Netlify dashboard access.
Fill in the actual values after #11 is complete.
Goal
Deploy the Keystatic admin UI to Netlify so team members can edit content at
https://docs.bread.coop/keystaticwithout running anything locally.Prerequisite: #11 (switch Keystatic from Cloud → GitHub mode, dev-only) must be complete first.
Background
Currently the admin UI is dev-only — Keystatic is conditionally excluded from production builds:
Keystatic needs server-side code to handle the GitHub OAuth callback and API requests
(
/keystatic/api/*routes). Since the project currently builds as a static site(no adapter), we need to add an SSR adapter to deploy these routes.
Architectural change
static(implicit default)hybrid(most pages static, Keystatic API SSR)@astrojs/netlifydist/(static files)localhost:4321/keystatichttps://docs.bread.coop/keystaticSteps
1. Install the Netlify adapter
Or manually:
This adds the adapter to
astro.config.mjs:2. Choose output mode
Two approaches:
Option A —
output: 'hybrid'(recommended)/keystatic/api/*) run as Netlify Functionsexport const prerender = falseon any non-API Keystatic pageOption B —
output: 'server'export const prerender = trueto static pagesStart with Option A.
3. Include Keystatic in production builds
Remove the production guard in
astro.config.mjs:Alternatively, keep the guard but add a separate env var for toggling the admin UI:
4. Configure GitHub App redirect URI
After deployment is working, add the production callback URL to the GitHub App
(created in #11):
or personal app settings
Without this, GitHub OAuth will fail in production.
5. Set env vars on Netlify
The four env vars from
.env(generated in #11) must be set in the Netlify dashboardor
netlify.toml. The Netlify site manager needs to add:.envto the repo. These are already in.gitignore.6. Update
netlify.toml(if needed)The current
netlify.tomlis minimal:With the adapter,
astro buildoutputs to bothdist/(static) and.netlify/(functions). The defaultpublish = "dist"should still work.No changes expected, but verify after
astro build.7. Build and deploy
Verify:
dist/contains static HTML (as before).netlify/functions-internal/contains Keystatic API function(s)npm run previewworks locally (simulates SSR)Deploy to Netlify (via git push or CLI):
netlify deploy --prod # or push to main for auto-deploy8. Smoke test the deployed admin UI
https://docs.bread.coop/keystatic/,/about/, etc.)/token→/about/bread-token, etc.)Netlify manager action items
The following must be done by someone with Netlify dashboard access.
Fill in the actual values after #11 is complete.
Add env vars to Netlify dashboard:
.envafter feat: switch Keystatic from Cloud to GitHub mode #11)KEYSTATIC_GITHUB_CLIENT_ID<TBD — from .env>KEYSTATIC_GITHUB_CLIENT_SECRET<TBD — from .env>KEYSTATIC_SECRET<TBD — from .env>PUBLIC_KEYSTATIC_GITHUB_APP_SLUG<TBD — from .env>Verify Netlify site is on a plan that supports Functions (Functions are included on all Netlify plans, including Starter)
Verify Netlify Functions timeout is adequate — default 10s should be fine for Keystatic API calls (max: 26s on Starter, 30s on Pro)
Netlify site ID:
<TBD>(needed fornetlify linkif running CLI locally)Netlify team/account:
<TBD>Rollback plan
If the SSR deployment causes issues:
astro.config.mjschange (re-add the production guard)ENABLE_KEYSTATIC=falsein Netlify env varsReference