Third-party integrations primer
The external dependencies this site talks to are, almost entirely, a handful of server-side data feeds that pull content from someone else's API — and the good news is they're all the same shape, so learn one and you can read or add any of them. (There are also a couple of avatar / build-time odds and ends, covered at the end.)
Just want the inventory? Skip to the map.
The server-side feed pattern
Every server-side integration is a Features/<Name>/ module (see the backend primer for why features get their own folder) built from the same four parts:
- An options class bound to an
appsettings.jsonsection — base URL, cache duration, any keys. - A named
HttpClientwith a sane timeout and aUser-Agent, registered in the feature's composer. - A service that fetches, deserialises, and caches with a stale fallback — so a slow or down upstream degrades to slightly-old data instead of a 500. (That caching shape is question 4 in the caching primer.)
- A composer — an Umbraco
IComposer, the startup hook where a feature registers its own services (RegisterSessionize,RegisterFeeds) — that wires the three together.AddComposers()discovers it; nothing else has to know the feature exists.
The three feeds:
- Sessionize (
Features/Sessionize/) — conference programme, speakers, and schedule from the Sessionize platform. Config sectionSessionize(EventId,BaseUrl,CacheDurationInMinutes);EventIdis the one bit you must supply per environment. Unlike the other two, it's surfaced to the browser through/api/sessionize/*endpoints (output-cached with theExternalApipolicy) and rendered by Lit components — so it has a frontend half too.SessionizeApiClientkeeps an in-memory cache and an on-disk fallback for when the API is unreachable. This is the most-documented integration: see the Sessionize section ofCLAUDE.mdfor the endpoint and component map. - Calendar Feed (
Features/Feeds/Calendar/) — community events fromumbracalendar.com. Config sectionCalendarFeed(Url,CacheDurationInMinutes). A public endpoint, no key;CalendarFeedServicekeeps a 7-day stale copy. Rendered server-side, not exposed as an API. - Community Blogs (
Features/Feeds/CommunityBlogs/) — aggregated community blog posts from an external community-content aggregation API. The richest of the three: aCommunityBlogsBackgroundServicerefreshes on an interval (RefreshIntervalInHours),CommunityBlogsApiClientpages through results, andCommunityBlogsImageDownloaderpulls featured images on its ownHttpClient. Config sectionCommunityBlogs— noteApiBaseUrlandApiKey, both secrets with no committed default: set them inappsettings.Local.json(or the Cloud portal). Rendered server-side; caches in memory with a disk copy and a 30-day stale fallback.
Both Calendar and Community Blogs register through one composer, Features/Feeds/Configuration/RegisterFeeds.cs.
Avatars and build-time
Worth knowing they exist, though they're hot-linked CDN/build-time bits rather than configured services:
- Member/MVP avatars (
Features/Mvp/Infrastructure/MvpDataService.cs) — avatars hot-link to GitHub (github.com/{handle}.png) when an MVP has a GitHub handle, falling back to a deterministic DiceBear avatar (api.dicebear.com/.../{seed}) when they don't. No config, no auth — public image URLs. - Doc contributors (
StaticAssets/devops/generate-doc-contributors.js) — a build-time script that reads git history for the docs and, if aGITHUB_TOKENis present in CI, resolves commit emails to GitHub accounts for the avatar chips on each rendered doc. Runs in CI, not at request time.
The map
| Integration | Where | Type | Config | Key/secret? |
|---|---|---|---|---|
| Sessionize | Features/Sessionize/ |
backend feed + /api/sessionize + Lit |
Sessionize section |
EventId per env |
| Calendar Feed | Features/Feeds/Calendar/ |
backend feed (server-rendered) | CalendarFeed section |
none (public) |
| Community Blogs | Features/Feeds/CommunityBlogs/ |
backend feed + background service | CommunityBlogs section |
ApiKey (Local/portal) |
| MVP / contributor avatars | Features/Mvp/, devops/ |
CDN hot-link / build-time | none / GITHUB_TOKEN (CI) |
— |
What isn't here (so you don't go looking)
The project's top-level description and some older docs mention integrations that aren't in this repo: Matomo, Intercom, and a Google Maps community map were never wired up or have been removed (the @googlemaps/* npm packages linger in package.json but no code uses them), and the GitHub release-tracking feature was extracted into a separate releases site. If you're hunting for any of those here, stop — they live elsewhere or not at all.
Adding a new integration
For anything server-side that calls an external API, follow the feed pattern above rather than inventing a new one: an options class bound to an appsettings section, a named HttpClient with a timeout, a service that caches with a stale fallback, and a composer to wire it up — all under Features/<Name>/. Put secrets in appsettings.Local.json (gitignored), never in the committed config. Promote to a Features/ folder once there's a client + options + service + DTOs that belong together; see the backend primer for the threshold.
Related docs
- Backend primer → Self-contained features — the
Features/<Name>/module shape these all follow. - Caching primer — the stale-fallback caching that makes the feeds resilient (question 4).
CLAUDE.md— the Sessionize feature in depth: endpoints, frontend components, deep-linking, and Open Graph.
Learn the feed shape once and the rest of the server-side integrations read the same. Adding one is mostly a matter of not being clever — copy the pattern, keep the secret out of git, cache with a fallback.