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.