Integrations, languages and performance

The site-wide capabilities: the external systems the site connects to, its languages, and how it stays fast at scale.

2026-11-07

Integrations

The external systems the Euro League site connects to. Contentful is always on. Most of the rest are switched on by environment: the code ships in this repository, and an integration comes on in an environment (local, develop, staging, production) when that environment sets its key or address. With nothing set, the integration is simply absent — no script loads and nothing is drawn — so a developer's machine and CI run without any of them. The variables are listed in Environment variables.

Content, data & media

Integration What it does Status Detail
Contentful (CMS) Where editors author all content (space 12gd2cvfgb6b, "Euro League"); the content model itself is defined in code Available (always on) Content model
Competition Engine ELB's competition data — teams, players, coaches, games, live scores, standings and statistics — behind every basketball page and widget Available (COMPETITION_ENGINE_BASE_URL) @v4/competition-engine
Stadion platform video SDK Supplies video metadata (videos, categories, collections, playlists, filters) for the video section Available (with video) Media package
Mux Euro League's video provider: Video Items hold their video in Mux, played through Mux's hosted player; also the muted inline previews Available The video section
Brightcove Alternative playback provider (HLS/DASH streaming) Available Media and video architecture
YouTube Alternative playback provider, and YouTube embeds in articles Available Media and video architecture
Scoreplay ELB's image library and dynamic-crop image CDN — the site's default image source; Contentful's image service serves images uploaded there instead Available @v4/image
WSC Sports (Stories / Moments) The clips rows: an editor's WSC block, and the team and player pages; their events go to the dataLayer, with consent Available (NEXT_PUBLIC_WSC_API_KEY) @v4/wsc
EuroLeague TV (Deltatre Vesper SDK) The Game Centre links out to EuroLeague TV. An embedded livestream player is built but not yet placed on any page In development (NEXT_PUBLIC_VESPER_API_KEY) @v4/eltv
ECAL "Add to calendar" on the Games page: a competition's or a team's schedule into the fan's calendar Available (NEXT_PUBLIC_ECAL_API_KEY) @v4/ecal
Integration What it does Status Detail
Google Tag Manager Loads ELB's GTM container; the site pushes the tracking plan's events (page views and interactions) to the dataLayer. Every tag lives in ELB's container — the site loads no GA4 or gtag.js itself Available (NEXT_PUBLIC_GTM_CONTAINER_ID) @v4/analytics
OneTrust The cookie banner and consent choices, passed on through Google Consent Mode v2. No event is sent before the visitor consents Available (NEXT_PUBLIC_ONETRUST_DOMAIN_SCRIPT_ID) @v4/analytics
Cortex (EuroLeague ID sign-in) Single sign-on: a Login control in the site header, the signed-in fan's session, and the sign-in the Code of Conduct report requires. Not yet used to unlock any video Available (CORTEX_SSO_BASE_URL) @v4/cortex-sso
Email (Code of Conduct reports) Sending a submitted In-Arena Code of Conduct report to ELB. No email provider is chosen yet: a local site logs the email, and any other environment answers that it cannot send Not built @v4/code-of-conduct
Visitor country The footer's sponsor rules by country, read from the request's headers (/api/geolocation), never cached Available —

Hosting & caching

Integration What it does Status Detail
Redis A shared cache, so one editorial change reaches every running copy of the app Available (CACHE_REDIS_URL) Caching at scale (Redis)
Cloudflare Edge caching of listings and home pages, purged by tag when an editor publishes Available (CLOUDFLARE_API_TOKEN, CLOUDFLARE_ZONE_ID) Edge caching & purge

Configuration slots with nothing behind them

The configuration schema (packages/template-config/src/schema.ts) has slots for these, but nothing in this site reads them: setting one switches nothing on. Each would be a build, not a configuration change.

Slot What it would be Status
Search (Algolia) Site search Not built
Realtime (Ably) / live match (Pulselive) A realtime feed and broadcaster data Not built — live scores come from the Competition Engine instead
Analytics with GA4 directly GA4 loaded by the site Not built — by design, GA4 is configured inside ELB's GTM container
Error monitoring (Sentry) Runtime error tracking Not built
Ads (Google Publisher Tag) Ad slots Not built
Site ticker A route-targeted ticker strip Not built in the site — editors can fill it in Contentful, but no page draws it
Gamification Polls, quizzes, fan engagement Not built

How a feature is declared, and how an environment variable switches it on, is governed by the typed configuration file apps/web/club.config.ts. See Template config and Features & domains.

Design & tokens

Integration What it does Status Detail
Figma (Ghost 2.0 and ELB's files) The components are built from Ghost 2.0 and ELB's own Figma files — ELB – Web – Core, Content and Basketball, and the EXT concept file — and their designs are checked against them Available (build-time) Token pipeline
Token Studio ELB's designers push the brand's design tokens (colours, type, the EuroCup and NextGen themes) straight into the repository, where they are generated into @v4/tokens-euro-league Available (build-time) @v4/tokens-euro-league

Figma and Token Studio are build-time integrations, not runtime ones — designers work in Figma, and the design tokens flow into the codebase through the token pipeline. They underpin theming and the whole component library, but the live site never calls Figma.

Internationalisation

The site is multi-locale from the ground up. It currently uses one locale, but locale-prefixed addresses, translatable interface copy and the process for adding a language are all Available; full right-to-left (RTL) language support has its foundations in place but is Planned.

Locales

The site can serve content and interface copy in several languages. Euro League runs one locale, en-US — the default and the only one (apps/web/club.config.ts → locales) — and new locales are added through a defined process, not a code rewrite.

Every address carries its locale first: en-US is served under /en, so the home page is /en, an article /en/news/{article} and a team /en/teams/{team}. An address without the locale (/news) redirects to the one with it. This is the segment routing mode in the configuration (the other mode, with no locale in the address, is for a single-locale site that does not want one).

Capability Status Detail
Locale-prefixed addresses Available (/en/…) Competition sections
Multiple content locales Available (the site uses one) Localisation
Per-locale content in Contentful Available Localisation
Adding a new locale Available (defined process) Localisation

The dictionary still carries label sets for en-GB, fr-FR and it-IT inherited from the template, with translation passes outstanding. They are not served by this site; confirm their state before promising a translated Euro League site in another language.

UI copy: the dictionary

Interface labels — button text, section titles, standard phrases — are managed through a dictionary. The code owns the vocabulary (the set of keys and their default English copy) in code; editors maintain the labels in Contentful, and a label they publish reaches the site without a deploy. A label is looked for in the requested locale, then in en-US, then in the default copy in code. This means the interface is fully localisable without a developer, while the set of things that can be localised stays typed and reviewed.

Capability Status Detail
Translatable UI copy Available Dictionary keys
Editor-maintained labels Available Dictionary keys
Promoting translations between environments Available Dictionary keys

Right-to-left (RTL)

The design and code layers anticipate RTL: the layout uses direction-aware CSS throughout, and the token layer ships a complete RTL typography set. But the design system's components were authored left-to-right only, so RTL is an engineering effort still to be completed rather than a finished capability.

Capability Status Detail
Direction-aware layout foundations Available RTL & motion
RTL typography tokens Available Token pipeline
Full RTL language support (shipped RTL locale) Planned RTL & motion

In short: if ELB asks for an RTL language (Arabic, Hebrew), the honest answer is that the site is built to support it and the groundwork is done, but shipping an RTL locale is a project, not a switch.

Performance & scale

The site is built to serve high traffic cheaply and fast. Everything here is Available today.

Static-first rendering

Every page is served as a pre-rendered shell with cached data: the parts of a page that do not change per visitor are built ahead, and the content inside them is read through the app's cache rather than from Contentful on every request. Listings are path-based — /en/news/page/2 and every filtered view are pages of their own — so they stay cacheable under filtering. Listings and home pages are also cached at the Cloudflare edge, in front of the app; article and content detail pages are served by the app itself, from its cache.

Basketball data is cached by how fast it changes: team lists, profiles, standings and statistics for five minutes, the schedule and an unplayed game for one minute, a finished game for five. Live answers are never cached — while a game can be live, the browser asks the site for it directly (see Sport).

Capability Status Detail
Pre-rendered shells, cached data Available Caching & revalidation
Edge caching (Cloudflare) Available, switched on by environment Edge caching & purge
Path-based (static) pagination Available Pagination & filtering

Targeted cache invalidation

Rather than rebuilding the site on every edit, the site refreshes exactly the pages a change affects. When an editor publishes, a webhook expires only the relevant cached content, and purges the same pages from the Cloudflare edge by tag; time-based limits act as a self-healing floor if a webhook is ever missed. The result is near-instant freshness with minimal recompute.

Capability Status Detail
On-demand, tag-based revalidation Available Caching & revalidation
Self-healing time-based fallback Available Caching & revalidation
Edge purge by tag on publish Available, switched on by environment Edge caching & purge

Multi-instance caching

Each deployed environment runs the app across several server instances, so it uses a shared Redis cache that lets one editorial change reach every replica. It is config-gated (on where CACHE_REDIS_URL is set) and isolated per environment — each environment has its own Redis, never shared — and off where it is unset (a single local instance needs nothing extra).

Capability Status Detail
Redis cache handler Available, config-gated Caching at scale (Redis)
Cache isolation per environment Available (by design) Scale & performance

Lean pages

A Lighthouse campaign in October 2026 cut what each page has to download and lay out. The site's styles are split by section: every page loads a shared stylesheet of about 140 KB compressed (it was one 3 MB file), and the video and basketball pages each add their own smaller part only where they are used. The brand's design values are declared once for the whole page rather than on every component, which cut style and layout work on the home page by roughly two-thirds.

A load-test script (scripts/loadtest/eviction-storm.mjs) checks that a mass cache refresh under heavy traffic is absorbed by serving slightly stale pages while fresh ones are built, rather than flooding Contentful. It is run against a real deployment with Redis, not in CI.

Capability Status Detail
Per-section stylesheets Available Scale & performance
Load test for mass cache refresh Available (run by hand) Scale & performance

SEO & discoverability

Capability Status Detail
Per-page metadata (titles, descriptions, social cards) Available SEO & metadata
Sitemaps Available Sitemaps
Custom error & not-found pages Available SEO & metadata

The scale story in one line

Pre-rendered pages with cached data, refreshed precisely when content changes, cached at the edge and shared across instances — so traffic spikes hit the cache, not the CMS or the Competition Engine. For the full picture see Scale & performance.