Thanks for helping with the site. There are two kinds of contribution, each with its own workflow:
- Creating or editing a post
- Changing anything else in the repo (components, scripts, styles, config, workflows)
Both follow the same rule: nothing merges to main without a review. Merging to main deploys the live site.
You need Node 22 (the version CI uses).
git clone <repo-url>
cd schoolofcities.github.io
npm install
npm run devnpm run dev serves the site locally with hot reload.
| Path | What lives there |
|---|---|
posts/<post-name>/ |
One folder per post. The folder name is the page URL. |
src/lib/ |
Shared components (ChartFrame, Header, Footer, ...), global styles (styles.css) and helpers |
src/routes/ |
Site routes and layout |
scripts/ |
validate.js, PNG export and optimization, CSS stripping |
static/ |
Files served as-is |
.github/workflows/ |
check.yml (runs on every PR) and deploy.yml (runs on push to main) |
A post folder contains:
| Item | Status | Purpose |
|---|---|---|
meta.json |
Required | Title, type, summary, authors, published date, license, protected flag, related documents |
+page.svelte |
Required | Body content |
charts.js |
Required | Chart metadata (ids, titles, sources, alt text, long descriptions, notes) |
charts/ |
Required | One <chart-id>.svelte per chart listed in charts.js |
data/ |
Optional | CSVs used by charts or offered for download |
images/ |
Optional | Static images, e.g. pre-rendered map PNGs |
published/ |
Generated | Exported PNGs, created by npm run export-pngs at the end. Do not edit by hand |
For example:
posts/topic-geography/
meta.json
+page.svelte
charts.js
charts/
chart-one.svelte
chart-two.svelte
data/
chart-one.csv
images/
map.png
published/
2026-09-08/
Every pull request runs npm run validate and a full build. You can run the validation yourself before pushing:
npm run validate # errors fail; warnings describe unfinished work
npm run validate:strict # warnings fail tooPlease don't run npm run build and commit its output. build/ is gitignored and CI builds and deploys the site itself.
-
Pull the latest
mainand open a new branch. -
Run
npm installandnpm run dev. -
New post only: create a folder inside
posts/.- The folder name becomes the URL. Use
kebab-casein atopic-geographypattern, e.g.foreign-buyer-tax-vancouver-toronto. - Do not put years or dates in the name.
- Copy the placeholder
meta.json,+page.svelteandcharts.jsfrom an existing post. - Set
"protected": trueinmeta.jsonso the page is password protected while in development.
- The folder name becomes the URL. Use
-
Draft or edit the text and charts.
- Every chart uses the standard
ChartFramewrapper. Look at an existing post for examples. - Use one component per chart, inside the
ChartFrame. Chart ids are alsokebab-case. The id is set incharts.jsand is the chart's unique URL (for sharing and embedding). - Each component must be named
charts/<chart-id>.svelteto match its id, or validation fails. - If you add your own images to
images/(e.g. exported from QGIS), optimize them now, not at the end: runnpm run optimize-pngs -- --post your-post-name. It writes a-opt.pngcandidate next to each original. Check it looks right (thin lines, small dots and small text are most at risk), then re-run with--acceptto replace the original. - Check your work against the post review checklist (
notes/post-review-checklist.md, kept alongside the project notes) covering chart design, accessibility, writing and metadata.
- Every chart uses the standard
-
Only edit files inside
posts/your-post-name/. If you find a bug or want a feature in the wider project, use Workflow 2 in a separate branch and PR. -
Push your branch and open a pull request. The
Checkworkflow runs validation and a build automatically. Fix anything it flags. -
Request a review.
-
Once the review is done and changes are made, finalize the post:
- Set the
publisheddate inmeta.json. - Run
npm run export-pngs -- --post your-post-nameto generate the downloadable.pngfiles for this post only. Don't use--all, which regenerates every post. - Set
"protected": falseinmeta.json.
- Set the
-
Push these final changes to the PR and request a final review and merge.
-
After the deploy finishes, open the live page and check that everything renders, the charts load and all buttons and downloads work.
This covers everything outside posts/: shared components, styles, scripts, routes, config and CI.
-
Pull the latest
mainand open a new branch. Give it a short descriptive name (e.g.fix-chartframe-download-button). -
Keep the change to one purpose. Bug fixes, features and refactors should each be their own PR.
-
Make your change and check it in
npm run dev. If you changed shared components or styles, look at more than one post, since they all use them. -
Run
npm run validateand fix any errors. -
If a change alters how posts are structured (
meta.jsonfields,charts.jsshape, file naming), updatescripts/validate.jsand the existing posts in the same PR so nothing is left broken. -
Commit with clear messages that say what changed and why.
-
Push and open a pull request. In the description, explain the problem, what you changed, and anything reviewers should look at (which pages are affected, screenshots for visual changes).
-
Request a review. Do not merge to
mainwithout one. -
After merge, watch the
Deployrun and check the live site.
Changes to .github/workflows/ and package.json (dependencies) deserve extra care: they affect every future PR and the live deploy.
Open a GitHub issue. For bugs, include the page URL, what you expected, what happened, and your browser. For visual problems, a screenshot helps.
The content and code in this repository are released under CC BY 4.0. Only contribute material you have the right to share under that licence, and cite data sources in chart metadata.