React Development
React development at OMAV defaults to server-side rendering, so that crawlers receive every word and first paint does not wait on a bundle. Client-only rendering is a decision with a measurable visibility cost, and it should be made deliberately rather than inherited from a framework default.
Interfaces machines can read and people do not wait for
React is the right tool for interfaces with genuine interactive state. It became the default for everything else as well, and that is where the cost appears: a marketing site or a content application rendered entirely on the client serves an empty shell to a large share of the crawlers that matter.
Our default is therefore server-side rendering, with client interactivity added where the interaction requires it rather than everywhere by habit. This is not a stylistic preference. If a page needs to be found, quoted or indexed, its content has to exist in the HTML response.
The second discipline is a performance budget enforced at build. Front-end performance regresses through ordinary feature work, and a budget that fails the pipeline is the only version of it that holds.
What a React engagement covers
Six workstreams, with rendering strategy decided first.
Rendering strategy per route
Each route assigned server rendering, static generation or client rendering on the basis of what it does and whether it must be crawlable, with the reasoning recorded.
Component library
Components with real states — loading, empty, error, disabled — and keyboard reachability, because those states are where hand-built interfaces usually fail.
State management
Chosen for the problem rather than the trend: server state and client state distinguished, and a library introduced only where the complexity justifies it.
Accessibility
Focus management, semantic markup and keyboard operation built in as the components are written, which is markedly cheaper than an audit and remediation later.
Performance budget
Core Web Vitals measured per route with a budget enforced at build, so regressions fail visibly rather than accumulating across releases.
Tests and documentation
Tests around behaviour rather than implementation detail, plus a documented component inventory so the next developer does not build a fourth button.
How a React engagement runs
Decide rendering
Route-by-route rendering strategy agreed against crawlability and interactivity requirements before any component is written.
Build the system
Component library with full states and keyboard support established first, so pages are assembled rather than improvised.
Assemble routes
Pages built from the library, with server and client boundaries explicit rather than emergent.
Budget performance
Core Web Vitals measured per route and a budget wired into the build so future work cannot silently regress it.
Hand over
Component inventory, rendering decisions and operational notes documented, with a walkthrough for the maintaining team.
Rendering strategies compared
Choosing per route rather than per project.
| Dimension | Server-rendered | Static generated | Client-only |
|---|---|---|---|
| Crawler receives | Full content | Full content | An empty shell |
| First paint | Fast | Fastest | Waits on the bundle |
| Content freshness | Per request | Per build | Per request |
| Infrastructure | A running server | A CDN | A CDN |
| Right for | Personalised, frequently changing | Marketing, docs, content | Authenticated applications |
| Wrong for | Purely static content | Highly dynamic content | Anything that must be found |
What React is not for
Not every site needs React. A content site with light interactivity is often better served by a simpler stack that produces HTML directly, with less to build, less to maintain and less to go wrong. Where that is the case we will say so, and we will say it before the estimate rather than after.
Server-side rendering also has a cost: infrastructure that has to run and be monitored, rather than files on a CDN. For genuinely static content, static generation gives the same crawlability without the running server, which is why the decision belongs at route level rather than project level.
- Server-side rendering is the default; client-only is a decision with a visibility cost.
- Decide rendering per route, not per project.
- Build the component library, with all its states, before assembling pages.
- A performance budget only works if it fails the build.
Questions buyers ask about this
Why insist on server-side rendering?
Because many crawlers, including several AI crawlers, receive whatever is in the HTML response and do not execute JavaScript reliably. If a page must be found, indexed or quoted, its content has to be in that response. For authenticated application screens it does not matter, which is why the decision is made per route.
Can you work with our existing React application?
Yes. We assess it route by route and change only what affects what a crawler receives or what users measurably wait for. A wholesale migration is rarely the right answer; a targeted change to the routes that must be public usually is.
Next.js or plain React?
Next.js for anything with public content, because it makes the rendering decision explicit and cheap to change. Plain React with a build tool is fine for a fully authenticated application where crawlability is irrelevant. We will not introduce a framework whose features you have no use for.
How do you handle accessibility?
As part of writing components rather than as a later audit. Focus management, semantic elements, keyboard operation and real error states are built in from the start. Retrofitting accessibility into a completed component library costs several times what building it in costs.
How is performance kept from regressing?
Core Web Vitals measured per route, with a budget enforced in the build so a release that breaches it fails. Performance reported in a monthly document regresses; performance that blocks a merge does not.
Marked up as FAQPage structured data, matching the visible text exactly.
Still not sure this is the right service?
Answer four questions and we will tell you which one fits — or that none of them do.
Tell us what you are trying to fix.
A short conversation about the objective, the constraints and the timing. If we are not the right fit, we will say so.