← Back to principles
UI
Embrace the Platform
Statement
Leverage native web capabilities, semantic HTML, and browser APIs instead of hiding them behind opaque abstractions. Always provide escape hatches to drop down a level when needed.
What this means in practice
The web platform is rich, well-documented, and constantly improving. Teams should reach for native capabilities first and only introduce abstractions when they deliver clear, measurable value over the built-in alternative.
Use semantic HTML elements (buttons, forms, dialogs, details/summary) rather than recreating their behaviour in JavaScript.
Prefer native browser APIs (Fetch, Intersection Observer, Form Validation, Web Animations, URL, History) over library wrappers that obscure them.
CSS capabilities (Grid, Flexbox, Container Queries, custom properties, :has(), view transitions) should be used directly rather than abstracted behind utility layers unless there is a proven need.
Frameworks and libraries are tools, not replacements for the platform — understand what they do under the hood.
Every abstraction should provide an escape hatch that lets developers drop down to the underlying platform API when the abstraction doesn’t fit.
Progressive enhancement is the default: core functionality works without JavaScript where possible, and enhancements layer on top.
Why this matters
Building on the platform rather than around it produces faster, more resilient, and more maintainable software.
Native elements and APIs are optimised by browser vendors and benefit from ongoing performance and accessibility improvements for free.
Developers who understand the platform can debug issues at the source rather than fighting through abstraction layers.
Abstractions that hide the platform create lock-in, increase bundle size, and become liabilities when requirements change.
Escape hatches prevent teams from being blocked when an abstraction cannot handle an edge case, avoiding costly workarounds or rewrites.
Platform-aligned code ages better — browser APIs are stable and backwards-compatible, while library APIs regularly break between versions.
New team members with web fundamentals can be productive immediately rather than learning bespoke abstractions.
Practices that meet this principle
Default to semantic HTML elements before reaching for a custom component (e.g. use before building a modal from scratch).
Audit existing abstractions periodically — if a native API now covers the use case, migrate towards it.
When evaluating a library, check whether the underlying browser API would suffice with minimal effort.
Ensure every wrapper or helper exposes the underlying API surface so consumers can bypass the abstraction when needed.
Use progressive enhancement: build core flows in HTML and CSS, then layer in JavaScript for richer interactions.
Keep framework-specific code thin — push logic into framework-agnostic modules that interact with standard APIs.
Stay current with platform evolution (new HTML elements, CSS features, Web API proposals) through regular knowledge-sharing.
Write integration tests against real browser behaviour, not mocked abstraction interfaces.
Validation
A project meets this principle when:
Semantic HTML elements are used wherever they provide the required behaviour, rather than custom JavaScript equivalents.
Native browser APIs are preferred and documented as the default choice; library alternatives require justification.
Abstractions expose escape hatches that allow consumers to access the underlying platform API.
The team can articulate what each major abstraction does at the platform level and why the abstraction is needed.
Core user journeys function without JavaScript or degrade gracefully when it fails.
Bundle size is not inflated by libraries that duplicate capabilities already available in the browser.
Regular reviews identify opportunities to replace custom code with newly available platform features.
Potential blockers
Legacy codebases built heavily on framework-specific patterns that are expensive to unwind.
Browser support gaps for newer APIs requiring polyfills or fallbacks in the short term.
Team familiarity weighted towards framework abstractions rather than underlying platform APIs.
Third-party component libraries that do not expose escape hatches to the native layer.