Skip to content

Customisation & Branding

Beyond the core lifecycle, adaptors typically tailor four things to make a deployment their own.

Branding covers the logo, colour scheme, fonts, wordmark and language, so the deployment carries the adaptor’s own identity.

Branding is declared per domain in a brand.json alongside the domain’s network.json (the code calls a domain a network). The reference blue_dot/brand.json carries:

KeyWhat it holds
brandName, wordmark, strapline, seeding organisation
logoVariants — default, with-strapline, on-light, on-dark, on-brand
coloursprimary, secondary and accent palettes, each a named hex list
logoShape, faviconTypeHow the mark is rendered

Overrides are partial. A sub-brand supplies only what differs. The reference repository ships blue_dot/upsdm/brand.json, which overrides just logoShape, faviconType and the page title, and inherits everything else.

Two more things to personalise:

  • UI theme. VITE_DEFAULT_NETWORK_THEME selects the colours of the Signals web app. If it is unset, the app uses the first value of VITE_NETWORK_ID, and then blue_dot. A value that matches no theme also falls back to blue_dot.
  • Login screen. The per-domain Keycloak login theme image is built alongside the realm. See Keycloak Setup.

The Signals web app ships six themes, one for each domain colour except Brown. Four of them have a published minimum standard: the list of fields every blue dot of that colour must have, so any organisation that uses it can share and find blue dots with others. The others are colours only, with no network.json yet. See Domains, Participant Types and Instances for each domain and its status.

Theme valueDomainMinimum standard
blue_dot (default)Blue (jobs)Yes, with brand.json
yellow_dotYellow (education)Yes, no brand.json
purple_dotPurple (persons with disabilities)Yes, with brand.json
orange_dotOrange (tourism)Yes, with brand.json
pink_dotPink (women’s work)None published yet, theme only
green_dotGreen (farming)None published yet, theme only

There is no Brown theme. The Yellow theme value is the folder name yellow_dot, which differs from the domain id set in its network.json, so set VITE_DEFAULT_NETWORK_THEME explicitly for a Yellow deployment.

The aggregator portal has no theme list of its own. It reads the brand and the participant type labels of the domain it is configured for, so the same portal runs for Blue, Purple or Yellow without code changes.

Operational settings specific to a deployment:

  • SMS gateway credentials
  • The phone number used for Voice AI calls
  • Admin email addresses for alerts and approvals
  • SMTP settings for transactional email

These follow the project’s configuration rules: declared in a config package, overridden per environment, never hardcoded. See Configuration for exactly which file each value belongs in, and Deployment for the values that must be set before a stack comes up.

Metrics and trend views for the adaptor’s own use: registration volumes, active versus at-risk participants, and discovery and connection rates over time.

The participant states and the tiles are already declared in the domain’s network.json, so no new code is needed. The examples below are from blue_dot; other domains declare their own states and tiles the same way.

Participant state comes from status_rules on each participant type (an entry in the domains field), evaluated against item age and recency of action:

StatusReference rule (blue_dot)
newJoined within the last 7 days
activeApplied or was accepted in the last 30 days
at_riskNo activity for 31–90 days
inactiveNo activity for 90+ days (default)

Tiles come from dashboard_tiles per participant type (profile-level and user-level), and roll-up buckets from the domain-level dashboard_buckets, which relabels raw action statuses into programme language. In blue_dot, actions a participant starts read create → Applied and cancel → Withdrawn, and actions they receive read create → Applications and accept → Shortlisted.

Tailoring a dashboard means editing those declarations, not writing new aggregation code.

A public page introducing the overall programme (what it is, who it is for) that links through to the underlying DPGs for registration and discovery rather than replacing them.

Keep the DPG as the system of record. A landing page that re-implements registration forks the consent and verification path and breaks the lifecycle guarantees.

The point of the split is that an adaptor’s customisations do not accumulate into a fork:

LayerOwned byChanges per adaptor?
Signals DPG, Aggregator DPGThe commonsNo
Domain, participant type and item schemasAdaptor, as configYes
Branding, theme, landing pageAdaptorYes
DashboardsAdaptor, as configYes

See Blue Dots as a DPG for why this boundary is drawn where it is.