Capitalisation
The web app sets text in capitals exactly where production does, and nowhere else.
The App Router site matches production's capitals. Production
(apps/web, what statshub.com runs) sets section labels, table headers, badges
and some buttons in capitals with Tailwind's uppercase class. The App Router
site is meant to look the same, so it uses the same class in the same places.
When a component is ported, keep its uppercase classes; when one looks
different from production, diff it against the production file rather than
deciding the case afresh.
There used to be a rule here that nothing in the product is set in capitals,
enforced by scripts/check-caps.sh in apps/web-app-router's lint. It was
withdrawn so the web app could match production, and the script is gone.
What still holds
Style the case, do not rewrite the text. Capitals come from the uppercase
class, never from toUpperCase() on text that is rendered. The string stays in
its natural case in the locale catalogs, so a screen reader, a copy-paste and a
translation all get the words rather than a shout.
Acronyms and codes keep their capitals, because the capitals are the term
rather than a style: BTTS, SOT, GK, H2H, O/U, AGS, xG, a locale's
EN.
toUpperCase() for matching is fine. positionSortOrder[position.toUpperCase()]
normalises a key before a lookup; nobody reads the result.
Data is data. A league called NWSL and a club called PAOK arrive from
the API in capitals and stay that way.