Web engineering

Web applications that hold up as they grow

Multi-route, authenticated, data-heavy applications that stay quick on ordinary hardware and usable with a keyboard. You get a working URL in the first two weeks and the whole codebase at the end.

  • Fixed scope
  • 14-day first demo
  • WCAG 2.2 AA
  • Full IP transfer

What makes web apps hard

A web application is not a website with a login on it. It is a long-lived program running inside a browser you do not control, over a network you cannot predict, against a database that grows every day. The genuinely hard decisions are about where work happens — server, edge, or client — and what each of those choices costs you eighteen months later, once the routes have multiplied and the data has stopped being small.

Speed is a distribution, not a number. A build can score beautifully in a lab and still feel sluggish for the slice of users on mid-range Android hardware or hotel wifi, so we measure at the 75th percentile of real sessions — the threshold Core Web Vitals grades against, and where the complaints come from. Accessibility behaves the same way: scanners catch labels and contrast, but not whether focus lands somewhere sensible after a dialog closes.

Constraints that shape Web Application Development work, what each forces, and how the studio responds
What is true of this workWhat it forcesWhat we do about it
Browsers and networks you cannot controlAssume slow devices and flaky linksRendering mode decided per route
Automated scans miss most keyboard faultsFocus and semantics need human checksKeyboard specs written per component
Sessions live across tabs and refreshesAuth state races the interfaceServer session cookie, guards fail closed
Row counts keep growing after launchAccess patterns must be designed earlyIndexes and pagination fixed at schema time
Features accumulate faster than they are removedBundles and latency drift upwardPer-route budgets fail the build

In scope

  • Route architecture and rendering decisions
  • Typed component library with keyboard specs
  • API schema, generated clients, runtime validation
  • CI pipeline with accessibility and budget gates

Not in scope

  • Native iOS and Android clients
  • Feature work and on-call past warranty
  • Brand identity and marketing site copy

Handled by

What we build

01

Route and rendering architecture

We decide per route whether it renders on the server, streams in, or hydrates on the client, and hold that in code. Getting it wrong surfaces as slow first paint.

Route rendering map
02

Accessible component system

A typed component library on accessible headless primitives, with keyboard behaviour, focus, and ARIA specified per component. Hand-rolled dialogs and comboboxes are where most accessibility failures begin.

Typed component library
03

Typed data boundary

One schema describes the API, generates client types, and validates payloads at runtime. Drift between what the server sends and what the interface expects causes production errors that never appear locally.

Schema and generated clients
04

Live and offline-tolerant UI

Optimistic updates, reconnection, and conflict handling where several people act on the same record at once. The hard part is what the interface shows while client and server disagree.

Reconnection and conflict spec
05

Field performance instrumentation

Real-user monitoring wired in before launch, reporting interaction latency, paint timings, and layout shift by route and device class. Lab scores say what to fix; field data says whether it mattered.

Real-user monitoring dashboards
06

Sessions, roles and guards

Auth that survives a real browser: session refresh without flicker, correct behaviour across tabs, guards that fail closed. Permission checks live on the server; the interface only mirrors them.

Route guard test suite

How the work runs

  1. 01Week 1

    Route and data map

    We enumerate every route with its data dependencies, auth boundary, and rendering mode, and mark which screens are read-heavy and which are interactive. This is where scope becomes countable and expensive routes get named early.

    You getRoute map with rendering modes

  2. 02Week 2

    First route live

    One real route goes end to end — schema, server, interface, auth, pipeline, deployed URL — inside the first fourteen days. It proves the architecture against your data and gives you something to click on.

    You getWorking URL behind your login

  3. 03Weeks 3 onward

    Build under budgets

    Features ship route by route behind preview deployments, assembled from a component system with keyboard and focus specs. A route that breaks its JavaScript or latency budget fails the build instead of reaching users.

    You getPreview URL per pull request

  4. 04Final two weeks

    Harden and hand over

    We load test against realistic traffic, tune queries that only fail under concurrency, and walk the keyboard paths by hand. Then repository, infrastructure, runbooks, and credentials move into your accounts and the warranty starts.

    You getRunbooks and full access transfer

What you are handed

  • Route map with rendering decisions
  • Typed component library with accessibility specs
  • OpenAPI schema and generated clients
  • Browser and component test suites
  • Per-route performance and bundle budgets
  • WCAG 2.2 AA conformance report
  • Real-user monitoring dashboards
  • Deploy, rollback and restore runbooks
  • Repository and credentials in your accounts

Typical stack

Interface

ReactTypeScriptNext.jsViteTailwind CSSRadix UI

Server and data

NodeDjango REST FrameworkPostgreSQLRedisDrizzleOpenAPI

Delivery

DockerGitHub ActionsTerraformVercelCloudflare

Quality and telemetry

PlaywrightVitestaxe-coreLighthouse CISentryOpenTelemetry

The calls we make, and why

Server rendering or a single-page app for the whole product?

Decide it per route, not once for the app

A real product has a marketing shell, a signup flow, a dashboard, and settings, and they do not want the same answer. Public and cold-entry routes render on the server; the workspace people sit inside for hours can hydrate once and behave like an app.

We’d choose otherwise whenthe whole product sits behind SSO and no route is ever publicly indexed

One full-stack codebase, or a separate front end and API?

One repository with a typed server boundary

Splitting early buys independence you rarely use and costs a versioning contract, two deploy pipelines, and a whole class of type-drift bugs. Keeping one repository means the schema, the generated client, and the screens move together in a single pull request.

We’d choose otherwise whena mobile app or partner integration already consumes the same API, or a separate team owns it

Where should the session live — a cookie, or a token in the browser?

A server-issued session cookie, HttpOnly and SameSite

Access tokens parked in browser storage are readable by any script that gets injected, and you inherit refresh, rotation, and log-out-everywhere yourself. A cookie moves revocation back to the server, where you can end a session without waiting for a token to expire.

We’d choose otherwise whenthe app and the API sit on unrelated domains where third-party cookies are blocked

Do we need real-time updates, or is polling fine?

Polling or server-sent events until the interaction is two-way

Sockets look cheap until you own reconnection, backpressure, sticky routing, and what the screen shows while client and server disagree. Refetching on window focus is honest, nearly free, and survives a flaky network without any of that machinery.

We’d choose otherwise whenpeople must see live changes from each other within a second, as in dispatch or collaborative editing

This fits if

  • Several teams edit the same records and changes collide daily
  • You sell into the EU or public sector, so accessibility is contractual
  • An internal tool has outgrown spreadsheets and now needs auth and roles
  • You want a clickable URL within weeks, not a status deck
  • The app is fast on your laptop and slow for everybody else

Look elsewhere if

  • You want a marketing site or blog; a CMS costs less
  • Requirements still move weekly, so fixed scope will fight you
  • You have an in-house web team and need only extra hands
EngagementFixed-scope build
Typical length8–14 weeks
How it startsSend your route list, or a link to the current app, and we scope it in one call.

Questions we get asked

What does a web application build actually cost?

There is no honest number before the route map: cost tracks route count and integration count, not design polish. We price after mapping, never on a first call — a figure quoted before anyone has seen your data model is a figure that will move, usually upward. Expect the map in days, then a fixed price against a fixed scope.

Who owns the code, and could another team take it over?

You own everything from the first commit. The repository lives in your organisation, infrastructure runs in your cloud accounts, and every credential is yours and rotated at handover. We deliver architecture notes, the data model, and runbooks for deploy, rollback and restore precisely so a different team can pick it up. No maintenance contract is required.

What happens when something breaks after launch?

Every build carries a 30-day warranty, and defects against the agreed scope are fixed at no cost. Error tracking and real-user monitoring are wired in before launch, so failures reach a dashboard instead of arriving as a customer email three days later. Past the warranty, on-call is a separate retainer with a named response window.

Is accessibility actually a legal requirement for us?

If you sell to consumers in the EU, very likely yes. The European Accessibility Act has applied since June 2025, and EN 301 549 — the standard conformance is judged against — tracks WCAG Level AA. US federal procurement under Section 508 asks for AA as well. We build to AA regardless, because retrofitting focus management means reopening finished components.

How do change requests work without the price moving?

Changes are priced as their own slice of work, never absorbed silently. Fixed scope only means something if both sides hold the line, so we log each request against the route map, tell you what it displaces, and quote it separately. Small trades inside a route you already own are usually free; new routes are not.

Tell us the requirement.

Thirty minutes with the engineers who would build it. You leave with a scope, a timeline and a fixed price — or an honest no, and the reason why.