BBroadsheet
Documentation

Everything you need to run Broadsheet

Setup, schema generation, TypeGen, deployment, and customization — the full reference in one place. The same details found in the project's README, laid out for reading rather than skimming.

Quick start

Requires Node.js 20+ and a free Sanity project. Install once at the repo root — this is an npm workspaces monorepo, so a single install wires up both apps.

$ npm install
$ npm run setup

npm run setup logs you into Sanity in the browser, creates or links a cloud project, writes apps/studio/.env.local and apps/web/.env.local, creates API tokens, and optionally loads demo content for you.

$ npm run dev:studio
Studio → http://localhost:3333
$ npm run dev
Site → http://localhost:3000

Prefer manual setup? Copy .env.example.env.local in both apps/web and apps/studio, and create a project yourself at sanity.io/manage.

Project structure

Two apps in one npm workspace:

FolderDescription
apps/web/Next.js 16 App Router site — articles, podcasts, columns, visual stories, RSS, search, Sanity TypeGen
apps/studio/Sanity Studio with the editorial schema and homepage content desk

Inside apps/web

app/ Pages and API routes
components/ UI components
config/ Site branding config (reads env vars)
lib/ Sanity client, GROQ queries, helpers
public/ Static assets (logo, favicons)
types/ Shared TypeScript types
schema.json Exported Sanity schema — generated, don't hand-edit
sanity.types.ts Generated query/document types — don't hand-edit
sanity.cli.ts Sanity CLI + TypeGen configuration

Environment variables

The essentials — see apps/web/.env.example for the full list, including RSS limits, homepage layout counts, and social links.

VariablePurpose
NEXT_PUBLIC_SANITY_PROJECT_IDYour Sanity project ID
NEXT_PUBLIC_SANITY_DATASETDataset name (usually production)
NEXT_PUBLIC_SANITY_API_TOKENRead token — frontend fetches published content
SANITY_API_WRITE_TOKENWrite token — server-only, used by /api/revalidate
SANITY_REVALIDATE_SECRETShared secret the Sanity webhook must send
NEXT_PUBLIC_FRONTEND_URLCanonical site URL — used in SEO, RSS, sitemap
NEXT_PUBLIC_SITE_NAMEPublication name — shown as text masthead by default
NEXT_PUBLIC_BRAND_COLORPrimary accent color (defaults to the rust in this design)
NEXT_PUBLIC_HEADER_BGHeader background color

Sanity Studio

Document types available in the editorial schema:

Type_typePurpose
ArticlearticleLong-form content, hero/main story flags, reviews
AuthorauthorWriters and podcast hosts
CategorycategoryNews, opinions, reviews, etc. — slug drives frontend routes
ColumncolumnColumnist sections on the homepage
PodcastpodcastAudio/video episodes
TopictopicEditorial topics
TrendtrendTrending tags
Visual storyvisualStoryFull-screen story format
Site settingssiteSettingsSingleton — About & Contact page copy

Content setup checklist

Open About & Contact in the desk and fill in mission/standards copy and contact emails — document ID must stay siteSettings
Create categories whose slugs match your routes (news, opinions, reviews) and mark nav items with Is Navigation item
Add at least one author, then set NEXT_PUBLIC_DEFAULT_AUTHOR_SLUG
Optional: create column documents and list their slugs in NEXT_PUBLIC_HOMEPAGE_COLUMNS
Publish articles with category, topic, and author — use Main story / Hero / Rank to control homepage layout

Schema & TypeGen

GROQ queries in lib/queries.ts are typed end-to-end. TypeGen is a two-step pipeline: step 1 exports your Studio schema as JSON, step 2 reads that JSON plus your GROQ queries and writes TypeScript types.

StepCommandRuns fromOutput
1. Schema extractsanity schema extract --path ../web/schema.jsonapps/studioapps/web/schema.json
2. TypeGen generatesanity typegen generateapps/webapps/web/sanity.types.ts

Run both in one shot from the repo root:

$ npm run typegen

Commands

CommandWhat it does
npm run typegenStep 1 + step 2, one-shot
npm run schema:extractStep 1 only (alias: schema:sync)
npm run typegen:generateStep 2 only — needs schema.json to already exist
npm run typegen:watchBoth watches running in parallel
npm run dev:typegenStep 2 watch only — pair with npm run dev:studio

While actively developing schema

Run Studio dev and the TypeGen watcher side by side — Studio dev keeps schema.json in sync automatically (via schemaExtraction in sanity.cli.ts), and the watcher keeps sanity.types.ts in sync with it and with your GROQ queries:

$ npm run dev:studio # terminal 1, keeps schema.json in sync
$ npm run dev:typegen # terminal 2, keeps sanity.types.ts in sync
$ npm run dev # terminal 3

apps/web/sanity.cli.ts is what points TypeGen at the right files:

typegen: {
  path: './lib/**/*.{ts,tsx}',
  schema: './schema.json',  // output from step 1
  generates: './sanity.types.ts',
}

After changing schema in apps/studio or editing a GROQ query in apps/web/lib, just run npm run typegen again if you're not already running the watchers.

Revalidation webhook

In Sanity, add a webhook that fires on publish and POSTs to your deployed site:

https://your-domain.com/api/revalidate

Configure it to send a secret header:

HeaderValue
x-sanity-revalidate-secretyour SANITY_REVALIDATE_SECRET

(Or send Authorization: Bearer <SANITY_REVALIDATE_SECRET> instead.) The route then:

Verifies the secret (required in production)
Applies main-story / hero rules when an article is published
Revalidates affected Next.js paths — including the homepage, category listings, and /sitemap.xml

Demo & seed data

Broadsheet ships fictional placeholder content, safe to redistribute. From the repo root, after setup:

$ npm run seed

Creates fictional authors, categories, ~22 articles, podcasts, and visual stories. Images come from picsum.photos placeholders; podcast audio uses a royalty-free demo MP3.

ContentCount
Site settings1
Authors4
Categories3
Topics6
Trends3
Columns2
Articles22
Podcasts4
Visual stories2

Never export your real production dataset. Use npm run seed:bundle to build a clean, isolated demo dataset first — that's what gets packaged for distribution.

Customization checklist

.env.local — Sanity project + site name + URL
NEXT_PUBLIC_SITE_NAME set — shows as a text masthead until logos are added
Optional: drop public/logo_light.png + logo_dark.png for automatic light/dark logos, no code changes
Replace public/icon.png and apple-touch-icon.png before launch
Fill in the About & Contact singleton in Studio
Set NEXT_PUBLIC_HOMEPAGE_COLUMNS to your column slugs
Set NEXT_PUBLIC_GA_ID, or leave blank to skip analytics

Deploy

Netlify (recommended)

Base directory: apps/web
Runtime: Next.js
Build command: npm run build
Publish directory: .next (relative to the base directory — not apps/web/.next)
Add every env var from apps/web/.env.example

The production build is pinned to webpack (next build --webpack in apps/web/package.json) rather than Next.js 16's new Turbopack-by-default build, to stay compatible with the current Netlify Next.js runtime. Safe to remove once that support matures.

Sanity Studio

$ npm run deploy:studio

Scripts reference

CommandDescription
npm run devWeb app dev server
npm run dev:studioStudio dev server
npm run buildProduction build (web)
npm run setupSanity login, project, env files, optional seed
npm run seedLoad fictional demo content
npm run seed:bundleExport a clean demo dataset for distribution
npm run typegenSchema extract + TypeGen generate
npm run typegen:watchBoth TypeGen steps, watching
npm run schema:extractSchema extract only
npm run deploy:studioDeploy hosted Sanity Studio

License

One purchase = one commercial project. Build it for yourself or for a single paying client per license — see the LICENSE file in your download for the full terms. Questions about licensing for multiple projects or agency use: hello@broadsheetkit.com.