What we build
Web and mobile products, backend platforms, design systems and interactive interfaces.
We work across web, mobile, cloud and interactive interfaces, taking products from first sketch through to production, then keeping them worth maintaining.
Web and mobile products, backend platforms, design systems and interactive interfaces.
Small teams, written decisions, and a build you can hand to your own engineers.
Tell us what you are working on. We will come back with how we would approach it.
The mix is decided by the problem in front of us, not by what we would prefer to build.
Dashboards, SaaS products, customer portals and internal tools, built on a typed stack that stays readable as the team grows.
Apps designed around how the work actually happens: offline capture, background sync, and the platform conventions users already know.
Early product thinking through architecture, delivery and the improvements that follow. Useful when the shape of the thing is still moving.
Data services, integrations, authentication and the APIs that hold a product together when several clients depend on them.
Versioned infrastructure, predictable deployments and enough monitoring to debug a problem without guessing.
Browser-based visualization, product configurators and real-time interfaces for products that need to be explored rather than listed.
We stay small on purpose. It keeps decisions traceable, and it means the person you brief is the person who writes the thing.
Nobody can say where a request actually sits, so everyone asks.
the part that matters
One place to look.
feat/one-place-to-look
Owner, stage and next action on one screen, so it gets asked once instead of five times.
We work out what the workflow actually is, where it breaks and who pays for it, before anything gets chosen to build it with.
Scope written in plain language and agreed before the first commit.
The system should still be explainable after the third team joins and the tenth feature lands.
Boundaries, data ownership and trade-offs documented as code lands.
No account layer relaying requirements, and no telephone game between the brief and the branch.
One shared channel, engineers on the call, decisions in writing.
Code, docs, config and access arrive in a state your team can pick up without us in the room.
Repositories, infrastructure and accounts in your name from the start.
We add a tool when the problem calls for it, not because the tool is having a good year.
Every dependency has a named owner and a reason it exists.
If any of that sounds like the way you already want to work, the first conversation is usually short.
Start a conversationThe same sequence runs through every engagement. Only the depth changes.
We map the problem, who it affects and what constrains it, then write down what a good outcome looks like in plain terms.
Scope, architecture and sequence are agreed together, so the technical plan and the product plan do not disagree with each other later.
Flows and interfaces are designed as a system, with states, edge cases and accessibility resolved before anything gets built.
Short cycles with working software at the end of each one, reviewed against the definition of done we set at the start.
Testing, performance work and observability, so the release behaves in production the way it did in review.
Handover, documentation and access transfer, then whatever level of ongoing work the product actually turns out to need.
Under a working interface there is data arriving, APIs answering, logic deciding and automation handling the routine. We build every one of those layers, and most of the work is making them agree with each other.
The surface people actually use. Screens, states, empty states and the error copy nobody plans for.
The services and contracts underneath. Where a request becomes a query, an answer and a record of both.
The judgement calls and the routine work. Rules, models and automations that act without being asked twice.
The layer people feel rather than read. Anything that has to respond immediately and look right while it does.
Request path
Four layers, one journey. A request enters at the interface and does not stop until something has been rendered back.
Representative builds, written up by the problem that started them and the work it took to close it. Client names stay out until the write-ups are approved. The engineering does not change either way.
An operations team was running the day out of shared spreadsheets, with no reliable answer to who owned what. We replaced them with a single console where every job, its owner and its stage sit in one view, and status stopped being something people had to ask for.
Routine customer questions about where an order is, what was agreed and what is owed were arriving by phone and email, and being answered by hand. A portal put the same answers behind a login, leaving the account team with the exceptions rather than the whole queue.
Crews were completing jobs on paper because the existing tool assumed a connection they rarely had. The replacement captures everything locally, syncs in the background when signal returns, and resolves conflicts without asking the person in the field to arbitrate.
These hold on every project, whatever the stack turns out to be. If one of them has to give way, we say so before the work starts rather than after.
The next person to open the file should not have to ring us to understand it. Names say what things are, the structure matches how the product actually works, and anything clever carries a note explaining why it earned its place.
Budgets are agreed while the design is still on screen, not discovered during testing. We measure again before release, on a mid-range device and a normal connection rather than on the machine it was built on.
Keyboard paths, focus order and colour contrast are part of finished. Every interactive element is reachable without a mouse, and screen reader labels are written with the component instead of retrofitted at the end.
Authentication, permissions and data handling are designed alongside the feature. We keep the smallest amount of personal data the job needs, and we say plainly where it is stored and who can reach it.
Every dependency is something a person has to keep alive. We take one on when it saves real work, check that it is maintained and that we could replace it, and prefer the platform's own tools when they are close enough.
Repositories, infrastructure, domains and third-party accounts are yours from the first day, in your name and on your billing. Nothing important sits in an account only we can open.
Notes live next to the code so they are updated in the same commit that changes it. You get a written record of decisions and their reasons instead of a wiki reconstructed from memory six months later.
We cover the paths that would hurt if they broke and the logic that is easy to get wrong, rather than chasing a coverage number. A failing build has to mean something, so flaky tests get fixed or removed.
Every engagement draws on some combination of these. Each one sits under a service area you can read about in full.
We stay with technologies we know how to debug at 2am, and add something new only when the problem genuinely needs it.
With a conversation, not a proposal. You tell us what the product needs to do and where it is stuck now, we ask the questions that change the answer, and you get back a written outline of the approach, a realistic timeline and the parts we think are risky. That costs nothing and carries no obligation. If we think you would be better served by a smaller piece of work, or by someone else, we say so at that point rather than after you have paid for a discovery phase.
It depends on scope, and anyone quoting before they understand the workflow is guessing. What we can tell you is how we price: a defined piece of work is quoted as a fixed scope with a fixed number, and open-ended work runs monthly with an agreed capacity. In both cases you see the sequence in advance, so you know what lands first and what can wait. Small integrations run in weeks. A platform that replaces a real operational process runs in months, and we would rather say that at the start than discover it at month four.
Usually, yes, and it is a good part of what we do. We begin with a short review of the current state: what it does, what is fragile, what would break if you changed it, and which of those actually matters to you. From there we propose the shortest sequence of changes that reaches your outcome. A full rewrite is the last option we reach for, not the opening move, because it throws away years of edge cases somebody already paid to learn.
Yes, and it works better than running a parallel track. We join your repositories, your board and your review process rather than setting up a second one beside it. Where your conventions differ from ours, we use yours, because the code has to make sense to your team long after we have stopped touching it.
Yes. Interface, API, data model and infrastructure are normally one engagement, which is the point: most of the awkward bugs in a product live on the boundary between two of those, and they are far cheaper to prevent than to negotiate between two suppliers later.
Both. An early product gets a narrower scope and a lighter architecture, and it should, but it gets the same standards for testing, security and handover. First versions have a habit of still being in production five years later, so we build them as though yours will be.
It usually does, and that is fine as long as it is visible. When a request will not fit the timeline, we say so while there is still room to reshape it, and we set out the options: move the date, drop something else, or narrow the request. What we do not do is absorb it quietly and hand you a surprise at the end.
Yes. Product configurators, real-time material and finish preview, interactive catalogues and data visualisation, built with WebGL and Three.js. The part people underestimate is performance: we test on mid-range phones, not just the machine it was built on, and we design a sensible fallback for the devices that cannot run it.
Usually. It works best pointed at one defined job, such as classifying a queue, pulling structured data out of documents, drafting a first version or making a search behave sensibly, rather than bolted on as a general assistant. We scope it against a task you can measure, design for the cases it gets wrong, and keep a person in the loop wherever being wrong is expensive.
Two options, and you choose. Either your team takes full ownership using the handover package, which is code, documentation, infrastructure and access in a state somebody else can pick up, or we stay on an agreed cadence covering updates, monitoring and defect response. Nothing about the first option is designed to make the second one necessary.
You do, from day one rather than at the end. Repositories, infrastructure, domains and third-party accounts are created in your name wherever possible, and transferred to you at handover where they are not. Nothing important should sit in an account only we can open.
Tell us what you are working on, where it is currently stuck, and what the product needs to do. We will come back with how we would approach it, what it realistically takes, and where the risk sits.
We reply to every enquiry within one business day.