Next.js 16 + React 19 + Tailwind CSS v4 with GitHub-backed CMS storage — webhook revalidation, LiveRefresh SSE, and content push from the admin UI.
A production-ready Next.js starter template with GitHub adapter for @webhouse/cms. Content is stored as JSON in a GitHub repo and pushed to your site via signed webhooks. The site revalidates instantly and connected browsers refresh automatically via Server-Sent Events (LiveRefresh).
This is the same as the nextjs-boilerplate but with three additions for GitHub-backed content:
- HMAC webhook endpoint —
/api/revalidateverifies signatures and writes pushed content to disk - LiveRefresh SSE —
/api/content-streampushes real-time updates to connected browsers .env.example— pre-configured environment variables forREVALIDATE_SECRET
- App Router — Next.js 16 with React Server Components by default
- Blocks — Hero sections, feature grids, and call-to-action blocks
- Richtext — Markdown content rendered with react-markdown
- Maps — OpenStreetMap/Leaflet embeds from
mapfields - SEO —
generateMetadatafrom_seofields, JSON-LD, OpenGraph, sitemap, robots.txt - Dark mode — CSS
prefers-color-schemewith manual toggle in the navbar - Webhook revalidation — HMAC-SHA256 signed POST to
/api/revalidatewrites content and revalidates paths - LiveRefresh — SSE endpoint auto-refreshes connected browsers on content changes
# Clone this boilerplate
git clone https://github.com/webhousecode/nextjs-github-boilerplate.git my-site
cd my-site
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local — generate a secret with: openssl rand -hex 32
# Start the dev server
npm run devOpen http://localhost:3000 to see your site.
| Variable | Required | Description |
|---|---|---|
REVALIDATE_SECRET |
Yes | HMAC-SHA256 secret shared between CMS admin and your site. Generate with openssl rand -hex 32 |
NEXT_PUBLIC_LIVE_REFRESH |
No | Set to true to enable LiveRefresh in production (auto-enabled in dev) |
NEXT_PUBLIC_SITE_URL |
No | Your site URL for sitemap generation |
cms.config.ts # Collections, blocks, and field definitions
.env.example # Environment variable template
src/
app/
layout.tsx # Root layout (navbar, footer, theme, LiveRefresh)
page.tsx # Homepage (reads pages/home.json)
[slug]/page.tsx # Dynamic pages (about, contact, etc.)
blog/
page.tsx # Blog listing
[slug]/page.tsx # Blog post detail
api/
revalidate/route.ts # HMAC webhook — receives content push, revalidates
content-stream/route.ts # SSE endpoint for LiveRefresh
sitemap.ts # Auto-generated sitemap.xml
robots.ts # robots.txt
globals.css # Tailwind v4 imports + theme + prose
components/
article-body.tsx # Richtext renderer (react-markdown)
block-renderer.tsx # Hero, Features, CTA blocks
navbar.tsx # Responsive navigation + theme toggle
footer.tsx # Site footer
map-embed.tsx # OpenStreetMap via Leaflet
live-refresh.tsx # Client component — SSE auto-refresh
lib/
content.ts # getCollection(), getDocument(), readGlobal()
content-stream.ts # SSE broadcast utility
content/
global/global.json # Site title, nav links, footer
pages/
home.json # Homepage
about.json # About page
contact.json # Contact page with map
posts/
getting-started.json # Sample blog post
using-blocks.json # Sample blog post
public/
uploads/ # Media files (images, PDFs)
| Collection | Description | Fields |
|---|---|---|
| global | Site-wide settings | Site title, meta description, navigation links, footer text |
| pages | Static pages | Title, block sections (hero/features/CTA), richtext, map, SEO |
| posts | Blog posts | Title, excerpt, richtext content, date, author, cover image, tags |
| Content | JSON files stored in a GitHub repo — edited via the webhouse.app admin UI |
| Push | Admin saves content and pushes to your site via signed webhook (/api/revalidate) |
| Revalidation | Webhook writes files to disk and calls revalidatePath() for affected routes |
| LiveRefresh | SSE endpoint (/api/content-stream) notifies connected browsers to refresh |
| Rendering | React Server Components read content via fs at build/request time |
| SEO | generateMetadata exports per page, JSON-LD for blog posts and pages |
| Layer | Technology |
|---|---|
| CMS | @webhouse/cms (GitHub adapter) |
| Framework | Next.js 16 + React 19 |
| Styling | Tailwind CSS v4 |
| Markdown | react-markdown + remark-gfm |
| Webhook | HMAC-SHA256 signature verification |
| Live updates | Server-Sent Events (SSE) |
| Language | TypeScript |
npm run dev # Start development server
npm run build # Production build
npm start # Start production server
npm run lint # Run ESLintWorks with any Next.js hosting provider that supports API routes:
- Vercel —
npx vercel(zero config, set env vars in dashboard) - Netlify — connect repo, build command
npm run build - Docker — add
output: "standalone"tonext.config.ts, use a Dockerfile - Fly.io — Dockerfile +
fly.tomlwithprimary_region = "arn"
Remember to set REVALIDATE_SECRET in your hosting provider's environment variables.
Instead of editing JSON files by hand, use the webhouse.app admin UI:
npx @webhouse/cms-admin-cliThis launches a local admin interface where you can visually edit pages, posts, and blocks. When configured with the GitHub adapter, content changes are pushed to your site via the webhook endpoint.
webhouse.app — the CMS that builds itself.
@webhouse/cms · npm · docs