This repository contains the Dark Matter Labs public website, built with Next.js (App Router) and Sanity as a headless CMS.
- Framework: Next.js (App Router, React 18, server components + client components)
- Styling: Tailwind CSS + custom global styles
- CMS: Sanity (content types such as initiatives, feed items, jobs, team members, studios, labs, arcs)
- Deployment: Vercel (recommended), with
vercel.jsonin this repo - Analytics: Simple Analytics (loaded via
next/scriptin the root layout)
app/(front-end)/– public facing site (home, feed, initiatives, jobs, static pages, etc.)api/– API routes (e.g. ISR revalidation)studio/– embedded Sanity Studiositemap.js– dynamic sitemap for static + Sanity-driven pages
components/– shared React components (navigation, feed, initiatives, team, popups, etc.)sanity/– Sanity configuration, client, and schemasstyles/– global CSS and Tailwind configurationpublic/– static assets (favicons, partner logos, etc.)
- Install dependencies
yarn install
# or
npm install- Configure environment
Create a .env.local file (not committed) and provide the required Sanity + Next.js environment variables. Typical variables look like:
NEXT_PUBLIC_SANITY_PROJECT_ID=xxxx
NEXT_PUBLIC_SANITY_DATASET=production
NEXT_PUBLIC_SANITY_API_VERSION=2023-01-01
SANITY_API_READ_TOKEN=optional_if_needed # keep this secret, never commit
SANITY_REVALIDATE_SECRET=some-long-random-string # used for Sanity webhooks, keep secretCheck sanity/env.js for the exact names used in this project.
- Run the dev server
yarn dev
# or
npm run devThe site will typically be available at http://localhost:3000.
Key document types (see sanity/schemas):
feedItem– items shown on the feed (projects, media, updates)initiative– long-running initiatives with detail pagesjobObject– job postings shown on/jobsand in the navbar counterdmlien– team members shown on the/teampagelab,arc,studio,partner– various entities linked from initiatives and feed items
The front-end uses sanity/lib/client.js and the sanityFetch helper to:
- Cache responses in production while using
no-storein development - Tag responses for revalidation via the
/api/revalidateroute
- All public pages live in
app/(front-end)/. - Global metadata and Open Graph defaults are defined in
app/(front-end)/layout.js. - Dynamic metadata for individual initiatives and feed items is generated via
generateMetadatain their respective[slug]/page.jsfiles. - A sitemap is generated from Sanity slugs and key static routes via
app/sitemap.js. public/robots.txtis configured to allow crawling of the site.
- Heavy pages that require interaction (home, feed filters, team interactions) are implemented as client components where needed.
- Images use
next/imageand Sanity image helpers where possible for optimised loading, responsive sizing, and blur-up placeholders. - Analytics are loaded with
strategy="lazyOnload"so they do not block first paint.
When making changes, prefer:
- Server components and static data fetching (
generateStaticParams) where possible - Streaming / Suspense for heavy sections
- Re-using Sanity queries and tags to keep caching behaviour predictable
Common package scripts (see package.json):
dev– start the Next.js development serverbuild– create a production buildstart– start the production serverlint– run linting
The project is designed to be deployed on Vercel:
- Connect the Git repository to Vercel.
- Configure the same environment variables used locally.
- Deploy from the Vercel dashboard or via
vercelCLI.
On deploy, Vercel will:
- Build the Next.js app
- Host static assets and dynamic routes
- Provide the
sitemap.xmlandrobots.txtendpoints automatically from theapp/andpublic/setup.