Customer-facing web applications
Where interaction complexity justifies a component-based front end and hiring availability makes the team sustainable.
React is a rendering library, not an architecture. Most of the trouble we are called in to fix comes from the decisions React deliberately leaves to you — state, data fetching, rendering strategy — being made implicitly.
React has become the default for enterprise front-end work, largely because of hiring availability and ecosystem breadth rather than because it is technically dominant. That is a legitimate reason and it shapes what goes wrong.
What React deliberately does not decide is the interesting part: state management, data fetching, routing, rendering strategy and how components are composed. Those decisions get made anyway, usually implicitly and differently in each part of an application.
Our work here is mostly architectural: establishing rendering strategy against real requirements, deciding where state lives, and treating accessibility and performance as requirements rather than as a later pass. Both are considerably cheaper to build in than to retrofit.
Where we see this used to good effect, and what makes each case a fit.
Where interaction complexity justifies a component-based front end and hiring availability makes the team sustainable.
Data-dense interfaces where component reuse across many screens pays back quickly.
A shared component layer across products, where consistency and accessibility are enforced once rather than per team.
Where server rendering serves the content and React handles the parts that genuinely need to be interactive.
Replacing an older front end screen by screen rather than in a single cutover the business cannot absorb.
Public sector and education services where conformance is an obligation and the component layer is where it is enforced.
The decision with the widest consequences is rendering strategy: client rendering, server rendering or static generation, chosen against real requirements for first paint, interactivity and search visibility rather than by framework default.
The second is where state lives. Applications that put everything into a global store make simple changes expensive; applications with no strategy at all end up with the same data fetched independently in six places, each with its own loading and error handling.
The practices that keep a React codebase workable are mostly about constraint. TypeScript throughout rather than partially, a component library used rather than bypassed, and a stated position on which patterns the codebase uses.
The most valuable and least glamorous is treating the component library as the only way to build UI. Where teams can drop to bespoke markup when convenient, accessibility and visual consistency both degrade steadily and nobody notices until an audit.
React escapes rendered content by default, which removes the most common injection class — until someone reaches for the escape hatch that injects raw HTML, which is where most front-end injection vulnerabilities we find originate.
The larger issue is architectural: what the front end is trusted to enforce. Authorisation implemented only in the client is not authorisation, and hiding a control does not restrict the endpoint behind it.
Front-end scalability is mostly about the codebase rather than traffic. Large React applications become slow to build, slow to test and difficult to change when boundaries were never drawn.
Where multiple teams contribute, the question is how to allow independent delivery without fragmenting the user experience. Micro-frontends solve a real problem and introduce substantial complexity, and they are adopted more often than the problem warrants.
Front-end performance is a commercial property in consumer contexts and an accessibility one everywhere: a slow interface excludes people on older devices and constrained networks, which in India is a large share of users.
The dominant costs are bundle size and unnecessary re-rendering. Both are measurable, both are addressable, and both are usually assessed on a developer's machine on a fast connection — which is the least representative environment available.
The integration that matters most is with the API layer, and the recurring problem is a front end shaped around endpoints that were designed for a different consumer — producing many round trips to assemble one screen.
Where the front end cannot change the API, caching and request coalescing help. Where it can, designing the interface around what the screen actually needs is usually the larger win and is frequently not attempted.
Front-end operations centre on release and observability. Client-side errors are invisible without deliberate reporting, and an application failing for a subset of browsers or devices can do so for weeks without anyone knowing.
Deployment is comparatively simple, and the property worth designing is the ability to roll back quickly — front-end regressions are highly visible and the fastest remedy is almost always reverting.
The governance that matters is the design system. Where it is genuinely the easiest path, consistency and accessibility hold across teams; where it is a recommendation, both degrade steadily and the drift is only visible in aggregate.
Accessibility governance belongs here too. Automated checks in the pipeline catch a meaningful portion, and the rest requires manual assessment — so the standard should state which is expected of whom rather than implying the scan is sufficient.
Sectors where this comes up most often, and the constraint that puts it there.
Traffic that is seasonal rather than steady, omnichannel inventory accuracy, and catalogue scale.
IndustryStudent information systems, hybrid delivery platforms and sharply seasonal load.
IndustryProcurement constraints, data residency, accessibility obligations and long-lived legacy estates.
IndustryInteroperability between clinical systems, patient data privacy, and legacy platforms that cannot be taken offline.
IndustryCore system modernisation, real-time payment flows, and architecture that can evidence regulatory controls.
IndustryReal-time tracking, partner system integration, and routing systems where latency has a direct cost.
The engagements this work is usually delivered within.
Custom application, web, mobile and API development, and modernisation of systems that are constraining the business.
Target-state design, modernisation roadmaps, integration and cloud architecture, and the governance that keeps decisions consistent after the consultants leave.
Test strategy, automation and performance testing, so quality is measured continuously rather than discovered late.
Delivery pipelines, infrastructure as code, Kubernetes and the observability practices that make releases routine.
Security architecture, assessment and compliance advisory, designed in rather than reviewed afterwards.
Migration strategy, landing-zone design, cost modelling and the architecture decisions that determine whether cloud spend buys capability.
Decided against requirements rather than by default. Server rendering helps first paint and search visibility; client rendering suits applications behind a login where neither matters much. Most applications need a considered mix, and the mistake is inheriting the framework's default without asking.
Start by separating server state from client state — they have different requirements and conflating them is the root of most state complexity we see. Server state wants caching and invalidation; client state is usually small enough that elaborate tooling is unnecessary.
Bundle size and unnecessary re-rendering, measured on representative devices and networks rather than on a developer machine. That last point matters more than it sounds: the development environment is the least representative one available, particularly for users on older devices.
Probably not. They solve a real problem — independent deployment by separate teams — at substantial cost in complexity and user experience consistency. They are adopted considerably more often than that problem is actually present.
Through the component library, so accessibility is built once rather than per screen, combined with automated checks in the pipeline and manual assessment for what automation cannot catch. Retrofitting accessibility into a delivered application is materially more expensive than building it in.
Yes, applied throughout. Partial adoption is the trap: it gives an impression of safety the type checker cannot actually provide, because it cannot reason about the untyped portions and reports silence rather than uncertainty.
Usually yes, screen by screen behind consistent routing and a shared design language. That is nearly always preferable to a cutover: it delivers value earlier and each increment can be assessed rather than the whole thing being judged at the end.
Only as a user experience convenience. Hiding a control does not restrict the endpoint behind it, and authorisation implemented only in the client is not authorisation. The server must enforce it independently, treating the client as untrusted.
First ask whether the API shape is right — a screen requiring six round trips usually reflects endpoints designed for a different consumer. Where the API can change, that is the larger win. Where it cannot, caching and request coalescing help materially.
Because client-side failures are invisible without deliberate reporting. An application broken for a particular browser or device can fail that way for weeks with no signal at all, which is why error reporting with enough context to reproduce is worth setting up early.
Yes, through software development, and we also take architecture and review engagements where your team builds and we assess rendering strategy, state design and accessibility.
Discuss a front-end architecture
A free first consultation covering your rendering strategy, where state lives, and whether the performance and accessibility position would survive measurement on a real device.
No cost, no obligation. Pricing is transparent and includes GST.