Platform Technical Guide
Technical reference for working in the CSDR Research Centre monorepo. Covers repository workflow, content structure, build commands, and asset management.
Repository Workflow
All changes go through branches and pull requests — never push directly to main.
Branch Naming
{type}/{project}/{description}Types: update feature fix access archive infra
Examples:
feature/climate-risk/add-q2-assessmentfix/platform/sidebar-orderingupdate/finance-dashboard/revenue-figures
Commits
Use the format: "type: description"
update: add Q2 climate risk datafix: correct sidebar ordering for archive projectsSubmitting Changes
- Commit your changes
- Push the branch
- Create a pull request:
gh pr create --base main
Binary Files
Files larger than 200 KB or binary formats (images, PDFs, spreadsheets, videos) must not be committed to git. Upload them to the asset library instead:
npm run upload -- <file> <project>They are then available at: https://assets.csdr.global/assets/{project}/{category}/{filename}
Categories: figures data outputs media misc
Exception: Small assets under 50 KB in the public/ directory (favicons, logos).
Content Structure
File Paths
All content lives under src/content/docs/{project}/. Each project has its own directory with an index.md entry point.
Frontmatter Fields
Every page requires frontmatter at the top of the file:
---title: Page Titleproject: climate-riskvisibility: internalcontent_type: reportsidebar_category: projects---| Field | Description |
|---|---|
title | Page title (displayed in sidebar and heading) |
project | Project identifier (matches directory name) |
visibility | Access tier: public, internal, client, restricted |
content_type | Type of content: report, reference, dashboard, presentation, archive |
sidebar_category | Sidebar grouping: projects, operations, archive |
Visibility Tiers
| Tier | Where it appears |
|---|---|
public | Internal site + public site |
internal | Internal site only |
client | Internal site + isolated spoke (email-gated) |
restricted | Sidebar link only; content in separate spoke (MFA-gated) |
Presentations
Slide decks use *** (three asterisks) as the slide delimiter. The first slide becomes a title slide automatically.
Build & Deploy Commands
| Command | Description |
|---|---|
npm run dev | Start local dev server |
npm run build:internal | Build internal site |
npm run build:public | Build public site |
npm run build:all | Build internal + PDF + DOCX |
npm run build:pdf | Generate PDFs only |
npm run build:docx | Generate Word documents only |
npm run upload -- <file> <project> | Upload asset to R2 |
Sidebar Generation
The sidebar is auto-generated from project index.md frontmatter. To regenerate after adding or modifying projects:
node _infrastructure/scripts/generate-sidebar.mjsThis outputs _build/sidebar-internal.mjs and _build/sidebar-public.mjs. Do not edit these files manually.
Sidebar Categories
- projects — All substantive work: research, client assessments, partnerships, advisory (not collapsed)
- operations — Centre administration, dashboards, internal tools (collapsed)
- archive — Completed and historical projects (collapsed)
Asset Management
Assets are stored in Cloudflare R2 and served from https://assets.csdr.global/.
URL Pattern
assets/{project}/{category}/{filename}Markdown Placeholders
Use these placeholders in markdown content — they are expanded at build time:
https://assets.csdr.global— resolves to the assets base URLhttps://subdomain.csdr.global— resolves to a spoke site URL
Domain Configuration
All domain URLs are centralised in config/site.mjs. Override via environment variables:
| Variable | Default |
|---|---|
BASE_DOMAIN | csdr.global |
SITE_PROTOCOL | https |
INTERNAL_SUBDOMAIN | internal |
PUBLIC_SUBDOMAIN | docs |
ASSETS_SUBDOMAIN | assets |