LOG 05 · LANGUAGE

React & TypeScript

Every component, hook, and shared module here is typed end-to-end — catching state-shape mismatches between independent systems before they ship, not after.

Published · Updated

Shared state without prop drilling

Some interactions need to reach across the component tree — a scroll-triggered camera move that a footer, a nav bar, and three unrelated section components all need to react to. Threading that through props would mean plumbing state through components that don't otherwise care about it. Instead, a small typed module-level store (a plain object with a `subscribe`/`setActiveIndex` pair) acts as the single source of truth; any component that cares imports it directly and subscribes, any component that doesn't never touches it.

TypeScript is what makes that pattern safe rather than fragile — the store's shape is a real interface, so a call site that gets the contract wrong (wrong argument type, a typo'd method name) fails at compile time instead of silently doing nothing in production.

Types as documentation

Function signatures double as the documentation for how a piece of shared logic is meant to be used — an optional second parameter on a navigation function, for instance, makes an 'instant, skip the animation' fallback path discoverable at the call site instead of buried in a comment three files away.

Typed dictionaries across three languages

This site ships in English, Spanish, and Portuguese, and the translation files are not three independent objects that happen to look alike. The English dictionary is the source of truth and the other two are checked against `Dictionary = typeof en`, so a key that gets renamed, misspelled, or forgotten in a translation is a compile error rather than the word `undefined` rendering on a live page in a language I am not reading every day.

The same idea covers the per-project copy. Localised project data is typed as a `Pick` of the canonical entry, which means a translation file can only override fields that genuinely exist, and adding a new field to the base type immediately tells me every locale that still needs it. Type checking is doing the job a translation-management process would otherwise have to do by hand.

Services that use this