03
Custom applications
Software built around your work and owned by you, for the people at the desk and the people in the field
We don't start from the screens. We start from who the actors are, what they may see and what happens when they get it wrong: the data model, the permissions and — last — the interface follow from there.
- Actors and permissionsWho they are, what they may see and what happens when they get it wrong
- Data modelThe entities and the boundaries between companies, before any screen
- Clickable prototypeTouched and discussed before building, while changing is still cheap
- Development in slicesEvery slice reaches someone's hands and brings an opinion back
- Automated testsThe paths that matter are repeated on every change
- Release and measureIn production with the numbers in view, not on a hunch
It's yours: code, data and keys
What we build for you is yours by contract, not under a licence to use. We hand over the source code, the instructions to rebuild the environment from scratch and the credentials for everything needed to run it. Without the last two the code alone is worth little, which is why they are delivered together.
The data stays yours and readable too: PostgreSQL, open formats, no obscure structure requiring our software to interpret it. The day you want to take everything elsewhere, that day should cost you days, not months.
It runs where you decide: on your servers, in colocation, on a private cloud or a public one. There is no piece of ours on the critical path, and no per-user fee growing as the company grows.
Software that is only yours, not a product to adapt to
The substantial difference from a subscription system is that nobody else shares that software with you: no compromises with other customers' needs, no updates changing your screens on a Tuesday morning, no price list deciding what you may do.
In exchange there is a responsibility worth stating: software of your own has to be maintained. Someone must update, fix and evolve it, and that someone must be chosen and paid. It is the bargain that makes ownership sustainable, and it is better made explicit at the start than discovered in year two.
If the platform serves several companies
Some projects don't end inside your company: they serve your branches, your partners or your customers, each with their own data. That is a different case from bespoke software for a single organisation, and it changes one thing in particular.
There the real question is not how the client list looks, but what happens the day a query forgets the company filter. If the check lives only in the code, that day one customer sees another's data and nobody notices: no error, no alert, just extra rows on a screen.
So when a project is of that kind, isolation goes inside PostgreSQL as row-level rules, and the application connects with a role that cannot bypass them. Code can be wrong; the database cannot. If instead the software is for you alone, this layer isn't needed and we don't add it: complexity that doesn't pay.
Fast from the first paint, in every language
Pages arrive already rendered from the server: it matters for the reader, who sees them at once, and for Google, which doesn't run JavaScript. The browser only takes over the parts that genuinely need to react.
Multilingual is structure, not translation bolted on: clean addresses per language, reciprocal links between versions and an explicit decision about what to show when a translation is missing.
One slice at a time, in people's hands
We don't deliver at the end of the project: we deliver pieces someone uses while the rest is still being built. Every slice is a complete function — not a pretty screen with nothing behind it — and it goes into the hands of whoever will actually use it.
It exists to catch, in time, the thing no analysis finds: that a feature requested with conviction turns out, once tried, not to be needed. Noticing that in week three is far cheaper than at final acceptance.
Before that, where the answer is uncertain, we build a clickable prototype: something to touch and argue about while changing your mind costs an afternoon instead of two weeks.
What breaks, and how we find out before you do
Every path that matters — signing in, ordering, paying — is covered by automated checks that run on every change and block the release when something doesn't add up. It isn't perfectionism: it is what lets you fix one thing without fearing you have broken another.
In production, errors reach us with the context of what the user was doing, not as a generic report. The practical difference is that a problem gets fixed the same day instead of after the third phone call.
Performance is measured on real devices, not on a developer's laptop: a page that opens in two seconds on your customer's phone is worth more than any theoretical optimisation.
Not depending on us
The technologies we use are widespread on purpose: if one day you want to change supplier, you will find people who can work on it without months of training. It is the opposite of what suits us in the short term, and the reason you can trust the rest.
Every structural choice leaves its reasoning written down — not a manual, two paragraphs. That is what lets you change your mind three years later knowing what you are touching, and lets another supplier understand the system in a day.
No piece should be understandable by one person only. If a project contains a part only its author can run, that part is your problem even when the code is yours.
For the people working away from a desk
The mobile app is the edge of the system: the point where data is born. If it is comfortable there, everything downstream works; if it is awkward, people go back to paper and the ERP tells a false story.
It has to survive gloves, sunlight, hurry and one free hand: few taps for the most frequent action, large type, clear confirmations. One codebase for iOS and Android, and where value or identity is involved, credentials stay inside the device's secure enclave.
What we build it with, and why
We don't use technologies because they are new: we choose them because they are widespread, maintained, and because somebody else has to be able to work on them after us.
Interface
- Next.js
- React
- TypeScript
- Tailwind
Pages arrive already rendered from the server: they appear at once and search engines read them without running code. TypeScript moves a whole class of errors from the moment a customer finds them to the moment the line is written.
Data
- PostgreSQL
- Row-Level Security
- versioned migrations
- Drizzle / Prisma
The database is not a warehouse but where the rules live: it decides who sees what, not the code. Every structural change is a versioned file, so the same database rebuilds identically in test and in production.
Access
- passkeys / WebAuthn
- second factor
- expiring sessions
- access log
Passwords are the weak point in almost every incident. Where possible we remove the password entirely; where we can't, we add a second factor and keep a record of who did what.
Field and mobile
- Flutter
- Dart
- iOS and Android
- offline capture
- secure enclave
One codebase for both systems, and an app that records even where there is no signal: if it stops working in a basement plant room, people go back to paper and the project is over.
Quality
- end-to-end tests
- Playwright
- code review
- automated checks on every change
The paths that carry money or data are repeated by a machine on every change. That is why things can be fixed quickly without the fear of breaking something else.
Delivery
- Docker
- rebuildable environments
- reversible releases
- verified backups
The environment is born from versioned files, not from a terminal session that went well. Every release can be undone in minutes, and backups are restored as a drill, not merely produced.
Portfolio
What we did on this, project by project.
SOS Bollette
CRM for a network of energy agencies
- A three-level model — network, company, person — where the tool perimeter is data owned by the network: a menu entry the partner doesn't have is never drawn.
- Isolation enforced by the database through row-level policies and an application role that cannot bypass them; the head office is a company with a different kind, not a privileged code path.
- Passwordless access: email links and passkeys, with sessions that remember which company you are working on.
- Full Italian tax profile (VAT number, tax code, SDI, certified email), company sheet read-only for operators who are not owners.
- Next.js
- React
- Prisma
- PostgreSQL
- Tailwind
- Playwright
ASC Buildings
Site app for a construction company
- Flutter app for construction site access management, designed for use on the move by people who are not sitting at a computer.
- Direct link to the company's ERP: what is recorded on site reaches the back office already assigned to the job.
- Flutter
- Dart
- iOS and Android
- Odoo
Manora
Mobile wallet of a blockchain platform
- Cross-platform app to operate on the chain: balances, transfers, history and multilingual notifications.
- Private keys never leave the device's secure enclave and biometric confirmation is mandatory to sign.
- On-device integration tests beyond unit tests, because on a wallet a mistake cannot be patched the next day.
- Flutter
- Dart
- secure enclave
- biometrics
Orbitas
Customer portal and operator console of a private cloud
- A monorepo with four applications — customer portal, operator console, API and marketing site — and shared packages for types, API client and UI library: one contract used by everyone, instead of four versions of the same thing.
- Compliance dashboard for the customer: security score, uptime against the declared target, incident history and a downloadable monthly report.
- Two very different audiences in the same codebase: whoever buys the service looks at numbers and evidence, whoever runs it needs operational tools. Separate interfaces, shared access rules.
- Next.js
- TypeScript
- Turborepo
- PostgreSQL
- Tailwind
- Zod
BigFishIta
This site: showcase, blog and private area
- Canvas hero with 300 frames following the pointer, progressively loaded and with an alternative for people who ask for reduced motion.
- Bilingual blog on PostgreSQL with a block editor in the private area: SEO, tags, scheduled publishing.
- Private area protected with mandatory second factor.
- Next.js
- PostgreSQL
- Drizzle
- Docker
Need this?
Tell us the problem and we'll tell you how we would tackle it — and if it isn't worth doing, we'll tell you that too.
Let's talk