# Community config — the community-manager control panel Everything a local community manager tunes for their community lives in **one file: `scopes.ts`**. Each community is one entry in `SCOPES`, keyed by its code — usually a country's two-letter code (`nl`, `be`, `pt`, …), or a city name for a city community (`barcelona`). Change a value, open a pull request, and the next deploy rebuilds that community's site. Every field below is documented inline in `scopes.ts` too (hover the field). This README is the friendly overview. Most fields are **optional with a sensible default**, so a new community only writes what differs from the norm. ## The knobs | Field | What it does | Default if you omit it | |---|---|---| | `social` | Your community's account: `{ did, handle }`. The DID is the real identity (survives handle renames); the handle is display only. Drives "Say hi", the footer follow, **and** is automatically an events source. | required | | `locales` | The languages your site is built in, in order. **The first is the default** shown at `/`; others live under `/` (e.g. `['es','en']` → Spanish at `/`, English at `/en`). | required | | `verify` | `true` shows the verifier page, homepage teaser and footer link. Set `true` only if you actually verify community members. | required | | `verifiers` | If verification is **delegated**, the verifier account(s) — `{ did, handle, url, remit }` each. A scope can have several (Spain has two, covering different groups); the /verify page lists them. Only meaningful with `verify: true`. | `[]` (you verify yourself, or nobody does) | | `managers` | The people who run this site, as **DIDs**. Shown as the site's managers **and** listed as members (deduped). Empty = the "help run this" invitation shows. | `[]` | | `memberSeed` | A manual starter list of members, as **DIDs** — people you vouch are part of the community before anyone signs in. Deduped with managers and everyone who signs in. | `[]` (the list still fills from sign-ins) | | `memberListUri` | A public Bluesky list to use as the member roster instead of the seed. | `null` | | `eventDids` | **Extra** atmo.rsvp accounts to pull events from, as `{ did, handle }` — beyond your own `social.did`, which is **always** included automatically. Use for sibling city chapters. | `[]` | | `feed` | Your homepage feed: `{ rkey }` of the custom feed generator (under gui.do's account). | `null` (no homepage feed) | | `nav` | Hide optional menu items: `{ members, stats, events, tools, builders }`, each `true`/`false`. `About`/home always show; `Verify` follows `verify`. | all shown | | `accent` / `accent2` | Your flag's two wordmark colours (pack names from `accents.ts`). | required | | `cities` | Cities to plot on the map, `Name: [lon, lat]`. | required | | `endonyms` | Each locale's name in its own language, for the switcher. | required | | `tier` | `'country'` (a national site) or `'city'` (a single-city community, e.g. Barcelona). A city behaves differently — see **City communities** below. | `'country'` | | `mapBox` | City only: `[west, south, east, north]` (lon/lat) to zoom the map to your region while the surrounding country colours the land. | auto-fit the country | ## Common tasks - **Add a manager** → add their DID to `managers`. (Resolve a handle to a DID at `https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=`.) - **Show your own events** → nothing to do: any atmo.rsvp event on your `social.did` appears automatically. To also pull a city chapter, add `{ did, handle }` to `eventDids`. - **Change the default language** → put that locale first in `locales`. - **Hide an empty section** (e.g. no tools yet) → `nav: { tools: false }`. - **Turn on the homepage feed** → set `feed: { rkey: 'atproto-' }` once the feed is published. - **Delegate verification** → set `verify: true` and list the verifier account(s) in `verifiers`. One entry renders a single card; several render a "pick your verifier" list (see Spain, which has two — one for Spanish speakers worldwide, one for accounts based in Spain). ## City communities (`tier: 'city'`) A city (e.g. `barcelona`) is **not** a country and never stands in for one. It sits inside a country (via `countries: ['es']`) for context, but behaves differently on purpose: - **Members are curated.** A city shows only `managers` + `memberSeed` + its own sign-ins, never everyone in the surrounding country (membership records are tagged by country, not city). So keep your roster in `memberSeed`. - **Stats are the country's.** There are no city-level population numbers, so the hero figure and `/community-size` show the surrounding country's estimate, labelled with the country ("in Spain"). - **The map shows your region, not a blob.** Set `mapBox` to frame it (Barcelona → Catalunya); the country still colours the land. (A landmark-silhouette treatment is being explored — see `brand/kit/barcelona/LANDMARK-MOCKUPS.md` in the workspace.) - **It's kept out of the country network.** A city is excluded from the `.eu` "Country communities" strip and the footer's national list; it appears in the city-communities directory instead. - **Verifiers can be shared.** A city can reuse its country's verifiers (Barcelona reuses Spain's). Two things a city also needs in the i18n (`src/i18n/`), not `scopes.ts`: a locative in `IN_COUNTRY` (e.g. `barcelona: { en: 'in Barcelona', ca: 'a Barcelona' }`) and, if you want the stats labelled differently, `stats.estimate` / `stats.count` overrides in that scope's `uiByScope` block. ## Rules that keep us safe - **Always DIDs, never handles** for identity (`managers`, `memberSeed`, `eventDids[].did`, `verifiers[].did`, `social.did`). Handles can be re-registered; DIDs can't. The tests enforce this. - Don't point anything at a `*.atproto.` handle as an identity key — those domains are borrowed. Background and rationale: `decisions/2026-09-21-centralized-country-config.md` in the workspace.