Most custom software replaces something that already functions: a spreadsheet, a shared inbox, a process one experienced person holds in their head. It works, right up until the company grows past the point where one person can hold it.
The usual first attempt is an off-the-shelf product. It covers eighty percent, and the missing twenty is the part that makes your business different from your competitors. So the team builds workarounds, keeps the spreadsheet running alongside it, and now maintains two systems instead of one.
When custom software fails, it is rarely for technical reasons. It fails because it was specified from a description of the process rather than from watching the process, so the version that gets built matches the org chart instead of the work.
The last failure is abandonment. A system gets built, the developer moves on, nobody wrote anything down, and three years later it runs on an unsupported framework that no one will touch.
Sound familiar?
A critical spreadsheet only one person fully understands.
The same data typed into three different systems.
A tool that covers most of the process and a workaround for the rest.
Reports assembled by hand at the end of every month.
A system nobody will change because nobody knows what will break.
Growth blocked by a process that cannot be delegated.
We work through the process with the people doing it, over calls and screen shares, and map what actually happens, including the exceptions that never make it into a brief. That map becomes the specification.
Not just the main workflow. Admin screens, roles, audit trails and the settings someone will need to change six months from now without calling a developer.
Accounting, CRM, email, storage, whatever the process already touches. The goal is removing duplicate entry, not adding a fourth place to type the same thing.
The numbers someone currently assembles by hand every month, generated instead. Exportable, because finance will always want it in a spreadsheet eventually.
Your spreadsheet or old database moved across, cleaned and reconciled against the original, with a parallel-running period before anyone depends on it.
How it works, how to deploy it, how to add a user, what the scheduled jobs do. Plus training for the people using it and a handover for whoever maintains it next.
The specification comes out of watching real cases rather than from a requirements document. Almost everything that goes wrong in internal software is an exception nobody thought to mention.
Sessions with the people doing the work, following real cases end to end over screen share. The exceptions and the workarounds are the valuable part.
Output: a process map and a written scope.
The main workflow built early and put in front of the people who will use it, before any of the surrounding features exist.
Output: a working core, tested by its actual users.
Remaining features, admin, permissions, reporting and integrations, delivered in fortnightly increments you can open and review.
Output: a complete system on staging.
Data migration, a parallel-running period, training sessions, documentation and a support window while the team settles in.
Output: a live system and its documentation.
Internal systems are read and modified for years by people who did not write them, so we favour boring, well-documented choices over interesting ones.
Laravel
Default for business systems: substantial logic, roles and permissions, admin panels and scheduled jobs. Straightforward for another team to pick up later.
Node and TypeScript
APIs and services, particularly where a TypeScript front end can share types with the backend and remove a whole class of integration bug.
React and Vue
Interfaces for anything genuinely interactive. Plainer than a consumer product, because these are tools people sit in for hours.
PostgreSQL and MySQL
Relational, because business data is relational. Postgres where JSON columns or full-text search are involved, MySQL where your team already runs it.
Queues and n8n
Scheduled and event-driven work: syncs, notifications, report generation, anything that should not happen inside a web request.
Docker and CI/CD
Reproducible environments and an automated deploy, so shipping a change is routine rather than an event someone has to be talked through.
Not fixed to these
This is what we reach for by default, not a limit. Internal systems usually have to live next to something that already exists: an ERP, a legacy database, a framework your in-house developer maintains. We build in those where it makes sense, and will say plainly when working around an old system will cost more than replacing the part that is in the way.
Internal systems are scoped by distinct workflows rather than by screens. Two screens doing the same job for different roles are one workflow, not two.
| Engagement | Typical timeline | Best for |
|---|---|---|
| Process mapping and scope | 1 – 3 weeks | Finding out what should be built, and whether it should |
| Single-workflow tool | 4 – 8 weeks | Replacing one spreadsheet or one manual process |
| Department system | 10 – 20 weeks | Several roles, permissions, reporting and integrations |
| Company-wide platform | 20 weeks + | Multiple departments and existing systems to connect |
| Support retainer | Ongoing | Changes as the process itself changes |
Process mapping is quoted on its own and is useful whatever you do next. More than one client has taken the map and concluded that a configured off-the-shelf product was enough after all, which we consider a good outcome.
Every project is priced in writing after a scoping call. You get a fixed number, with what is included and what is not, so there is nothing to negotiate later.
Tell us what you need built and we will send a scope and a price. The reply comes from the person who would run the project.
Get a quote →This page describes how we prefer to work, not a fixed contract. Deliverables, stages and timelines vary with the size and shape of the project, and some of what is described here will not apply to yours. The written scope you receive after the scoping call is the version that counts. How we engage →
Often you should, and we will say so. Custom is worth it when the process is genuinely particular to your business, when the workarounds are already costing real hours every week, or when per-seat licensing at your headcount exceeds the cost of building. If none of those apply, a configured product is cheaper and we would rather tell you now.
By walking through the work with the people who do it rather than reading a description of it, and by putting the core workflow in front of real users in week four rather than week twenty. The expensive failures are the ones discovered at handover, and they are nearly always an exception that never made it into the brief.
It will, which is why the system is built to be modified and documented well enough that someone else can modify it. Most clients keep a small retainer for ongoing changes. Some hand it to their own developer, which is equally fine and is the point of a clean handover.
Usually. Anything with an API, a database we can read, or even a scheduled file export can be connected. Older systems sometimes need a middle layer, and we will tell you during scoping if an integration is going to be the difficult part of the project rather than an afterthought.
You do, in your repository from the first commit and on your own infrastructure. No licence, no per-seat fee, and nothing that prevents another developer taking it over.
Migrated, cleaned and reconciled against the original before go-live, with a period where both systems run in parallel. Source data is always messier than anyone expects, and the cleanup is part of the scope rather than a surprise halfway through.
Every enquiry gets a reply within one working day, from the person who would run your project.