Custom software development
Custom Software Development with Next.js
Software built for one business rather than configured from a product. What that costs, what it buys, and the cases where buying something off the shelf is the better answer.
Custom software is software that exists because a business does something specific, and no product models that thing closely enough to be worth bending.
That is the whole definition, and it is also the first thing to test. A good deal of what gets commissioned as custom software is a product with a logo changed, and a good deal of what gets bought as a product becomes custom software anyway through two years of workarounds. Both are expensive mistakes and both are avoidable in the first conversation.
What this actually means in practice
The work is almost always one of three shapes.
An operational system - the thing a team works inside all day. Quotes, jobs, cases, stock, schedules, approvals. It is usually replacing a set of spreadsheets, an inherited application nobody can change, or both at once.
A customer-facing surface over systems that were never designed to have one. A portal, a tracking page, a self-service account, a booking flow. The hard part is rarely the screen; it is that the data behind it lives in something old and answers slowly.
An internal tool that exists because a product cannot do the one thing that matters. These are the smallest and frequently the highest-return engagements, because the alternative is somebody's week.
Why a server-rendered application and not a single-page one
For years a browser application meant three things to build: a front end, an API to feed it, and the glue between them. A large share of the code in those systems existed only to move data between two parts of the same application.
An App Router application removes that tier for most screens. The server reads the data and renders the page. The browser receives markup rather than a bundle that then asks for the data it needs. JavaScript ships only where an interaction genuinely requires it, which on an operational system is a minority of screens.
The practical effects are mundane and they compound. One language across the whole application rather than two. One repository and one deployment rather than two that version independently. A page that is correct when it arrives instead of correct a moment later. And meaningfully less code, which is the only reliable way to reduce the cost of the second year.
Which routes render which way is still a decision rather than a default, and it is the first architectural conversation on every build. The rendering model sets out what each option costs.
Where the data lives is decided at the same time
A custom application is mostly a data model with screens attached, so the schema is not a detail to settle later.
The decisions that are expensive to reverse are the ordinary ones. What is an entity and what is a field. Where money and dates are stored and in what type. Whether a record can be deleted or only superseded. Whether a status is a column or a history of transitions - which is the difference between a system that can say what happened and one that can only describe the present.
PostgreSQL is the default on these builds, for reasons set out on the PostgreSQL page. It is a default rather than a rule, and the one real operational trap - connection count under a serverless runtime - is a known problem with a known answer rather than a surprise.
How an engagement runs
Phases, each ending with something deployed.
The first phase is small on purpose. It takes the narrowest slice that is genuinely useful - one workflow end to end rather than the skeleton of five - and puts it in front of the people who will use it. That does two things: it settles the architecture against real data instead of against a document, and it gives everybody an honest basis for estimating the rest.
Scope for each phase is fixed in writing before it starts. Your engineers review pull requests from the first week if you have them, because that is how the conventions transfer and it is the only version where the code is still maintainable after we leave.
What you receive
At the end of each phase, a deployed application you can use - not a demonstration environment and not a branch.
With it: the repository, with the git history intact and no dependency on us to build or deploy it. An architecture note that says which routes render which way, where the client boundary sits and why, written while the decisions were being made rather than reconstructed afterwards. The database migrations as code, so the schema has a history rather than a current state. A deployment that runs on infrastructure you control if that is a requirement. And a list of what we did not do, with the reasoning, because the things deliberately left out are the part a handover usually loses.
When this is the wrong engagement
Worth saying plainly, because the answer is sometimes no.
If a product exists that does eighty per cent of what you need and the other twenty is preference rather than process, buy the product. Configuration is cheaper than code and it stays cheaper every year.
If the requirement is a handful of pages and a contact form, this is a website. A content management system with good templates will serve you better than an application with no maintenance budget behind it.
If the process is still being invented, software will freeze a decision nobody has made yet. Run it manually or in a spreadsheet until the shape stops moving, then automate the shape that survived.
And if nobody internally owns the result - no person whose job improves when it works - it will be abandoned regardless of how well it is built. That is the failure we see most often and the one that has nothing to do with engineering.
