Development Stack
The technologies we use in our products and projects
This page exists to show, plainly, what our products and projects are actually built with. Across mobile, web and everything behind them, every tool here was picked for performance, scalability and security first. No mystery stack, no proprietary framework you can never hire for. This is the full list of what your project will run on, what each piece is for, and when something else fits the job better.
Design
The interface tools used to turn a rough idea into screens you can click through. Every project is agreed here first, because a change costs minutes in a design file and days in a codebase.
-
Figma
Cloud based interface design, prototyping and a component library you keep. Screens get signed off here before production code exists.
-
Adobe XD
Vector wireframing and clickable prototypes, used when your team already works inside the Adobe ecosystem.
-
Sketch
macOS design tool for precise interface and icon work, mostly on projects that arrive with an existing Sketch library.
-
Canva
Store artwork, social assets and pitch decks that need to look right without a full design pass.
Mobile App Development
What high performance iOS and Android apps get built with. Cross platform by default to keep the budget sane, native the moment the product depends on platform features.
-
Kotlin Multiplatform (KMP)
The default for anything that has to reach both stores on one budget. Business logic, networking and data are written once in Kotlin, while each platform keeps its own fully native interface layer.
-
Kotlin
The language for native Android work and the shared layer in KMP: null safety, coroutines and far less ceremony than the Java it replaced.
-
Android
The platform itself, targeted down to older OS versions because that is what most of your users are actually holding.
-
Jetpack Compose
Declarative Android UI that removes the XML layout tax and makes state driven screens far easier to reason about.
-
Swift
Native iOS work where Apple frameworks carry the product: HealthKit, App Clips, complex gestures or heavy Core Data usage.
-
SwiftUI
Apple declarative UI framework for iOS screens that need to feel unmistakably native on current devices.
-
iOS
Builds signed, tested on real devices and submitted through App Store Connect under your own developer account.
-
Compose Multiplatform
Extends Compose beyond Android so one declarative UI can also cover iOS and other targets, on top of the same KMP foundation, when a shared UI is worth it over per platform screens.
-
React Native
Used when a team already lives in React and wants a mobile build that their web developers can maintain.
-
Java
Still the language of many working Android codebases. Maintained and extended without a forced rewrite.
-
Android Studio
Profiler, layout inspector and device emulation. Where Android performance problems get found before your users do.
-
Xcode
The iOS build, signing and instrumentation toolchain, plus the simulator matrix used before every submission.
-
JavaScript
The runtime under React Native and the bridge to any web view a mobile product needs to embed.
-
XML
Legacy Android layouts, manifests and resource files, still where a large share of shipped Android apps live.
Web Frontend Development
What responsive websites, dashboards and custom interfaces are built with. Typed, server rendered where it matters for search, and fast on a mid range phone.
-
HTML
Semantic markup that screen readers and search engines can both read, rather than a page made entirely of nested containers.
-
CSS
Modern layout with grid and flexbox, written so a phone gets the same care as a desktop.
-
JavaScript
Kept deliberately light. Interaction is progressive so the page still works while a script is loading.
-
TypeScript
Every non trivial frontend gets types. It catches the class of bug that only appears in production weeks after launch.
-
React
Used when a team already lives in React or the project needs an ecosystem package with no equivalent elsewhere.
-
Vue.js
First choice for admin panels and dashboards. The composition API keeps large forms and tables manageable.
-
Angular
For enterprise frontends that want strong conventions and a batteries included framework out of the box.
-
Next.js
Server rendering and static generation for React projects where search visibility and first paint decide the outcome.
-
Tailwind CSS
Design decisions stay in the markup where they are visible. No orphaned stylesheets and no naming debates.
-
Bootstrap
A dependable grid and component set for admin tooling that has to be built quickly and handed over.
-
Bulma
A lightweight CSS framework for small marketing builds that need structure without a JavaScript runtime.
-
Material UI
Ready made accessible React components for internal tools where custom design would be wasted effort.
-
Vite
Instant dev server and a build step that stays out of the way. Hot reload that actually reloads in under a second.
-
Redux
Predictable state for React applications large enough that passing props stops being honest about the data flow.
-
Axios
HTTP client with interceptors for auth tokens, retries and the error handling every real API integration needs.
-
VS Code
The everyday editor for web and backend work, kept deliberately light so it starts fast on any machine.
Backend Development
The secure, scalable side that powers web apps, mobile apps and everything in between. Chosen so you can hire for it later without a rewrite.
-
Laravel
The backbone of nearly every project. Queues, scheduling, auth, storage and migrations that make a handover painless.
-
PHP
Modern PHP with strict types and readable domain code. Cheap to host, easy to hire for, fast enough for most products.
-
Python
Data work, automation scripts and anything that touches machine learning libraries or scheduled processing.
-
Java
For enterprise services and integrations where an existing JVM platform is already the standard.
-
Kotlin
Server side Kotlin for teams that want one language across their Android app and their backend services.
-
Go
Small, fast binaries for services where concurrency and a tiny memory footprint matter more than framework features.
-
Rust
Reserved for performance critical components where memory safety without a garbage collector earns its complexity.
-
Node.js
Websocket servers, notification workers and services where an event loop suits the job better than a request cycle.
-
Express.js
A minimal Node framework for small APIs and internal services that do not need a full application stack.
-
NestJS
Structured, typed Node applications for teams that want conventions rather than a folder of loose route files.
-
Django
Python projects that benefit from a mature ORM, an admin interface and strong defaults on day one.
-
Flask
A light Python framework for focused services and internal endpoints that should stay small.
-
Symfony
Component driven PHP for systems that want explicit architecture and long term enterprise support.
-
Spring Boot
The standard for JVM services, used when a client platform is already built around the Java ecosystem.
-
Ktor
Lightweight asynchronous Kotlin services that share models directly with a Kotlin mobile client.
-
REST
The default API style because it is boring, cacheable and every client on earth already understands it.
-
GraphQL
Used when a mobile client needs to shape its own payloads instead of waiting for a new endpoint.
-
JSON
The transport format for every API contract, versioned and documented so clients are never guessing at a field.
-
Postman
Every API ships with a collection so your next developer can explore endpoints without reading the source first.
-
Swagger
Generated API documentation that stays in step with the code instead of drifting into fiction.
-
IntelliJ IDEA
The IDE for JVM and Kotlin work, with the refactoring and debugging tools that large codebases demand.
-
Linux
Where everything ultimately runs. Servers configured, documented and handed over rather than kept a mystery.
Databases & Storage
Where your data actually lives. The choice here outlives every other decision on this page, so it is made on the shape of your data rather than on fashion.
-
MySQL
The safe default for transactional data. Well understood, hosted everywhere, quick to tune when a query starts dragging.
-
PostgreSQL
Preferred when the data model gets interesting: JSON columns queried like tables, geospatial work, strict constraints.
-
SQL
Hand written queries and indexes where an ORM would quietly generate something slow at scale.
-
SQL Server
For integrations with existing Microsoft infrastructure and reporting stacks already built around it.
-
SQLite
On device storage for offline first mobile apps, so the app still opens on a train with no signal.
-
MongoDB
Document storage for content that genuinely varies in shape rather than data forced into a schemaless store.
-
DynamoDB
Managed key value storage for serverless workloads with predictable access patterns and unpredictable traffic.
-
Redis
Sessions, cache, rate limiting and the queue backend. The cheapest performance win available on almost any project.
-
Elasticsearch
Full text search and log analysis once a database LIKE query stops being a serious answer.
-
Firebase
Push notifications, crash reporting and analytics on mobile, and occasionally the whole backend for a prototype.
Dependency & Version Control
How dependencies are managed, builds are automated and history stays readable. All of it lives in your accounts, from the first commit.
-
Git
Small commits with readable messages. The history is part of the deliverable, not a private scratchpad.
-
GitHub
Repositories, pull requests and code review created under your ownership with us added as a collaborator.
-
GitLab
For teams that self host their source control or already run their pipelines on GitLab CI.
-
Bitbucket
Used when a client organisation is standardised on Atlassian tooling alongside Jira.
-
Gradle
Android and JVM builds with pinned versions, build variants and reproducible release artefacts.
-
Maven
Dependency management for established Java projects where the build is already defined in POM files.
-
npm
JavaScript packages with a committed lock file, so the build you ship is the build that gets rebuilt years later.
-
Composer
PHP dependencies pinned and audited, with updates scheduled monthly rather than chased on release day.
Testing Tools
What keeps a release honest. Tests on business logic, payments and anything touching user data are part of the build, not a line item.
-
JUnit
Unit and integration tests for Android and JVM code, run on every push before a branch can merge.
-
pytest
Python test suites with fixtures that make failure messages actually explain what broke.
-
Postman
Automated API collections that verify contracts and catch a breaking change before a client app does.
-
Insomnia
A lighter API client for exploring endpoints and debugging auth flows during development.
-
Selenium
Browser automation for legacy suites and cross browser checks on established web platforms.
-
Cypress
End to end tests that drive the real interface, with a video of the failure when something breaks in CI.
-
Playwright
Fast, reliable cross browser testing including mobile viewports and the flows that matter most.
-
SonarQube
Static analysis for code smells, duplication and security hotspots, reported on every pull request.
Deployment Tools
How the work reaches production, and how it gets rolled back if it should not have. If a branch is green it can go live without anyone running a script by hand.
-
Docker
Every project ships with a compose file, so a new machine is productive in one command and staging matches production.
-
Kubernetes
Container orchestration for products that genuinely need horizontal scale and zero downtime rollouts.
-
GitHub Actions
Tests, static analysis and deployment on every push, with the pipeline configuration living in your repository.
-
Nginx
Reverse proxy, TLS termination and static asset delivery. Configured once, documented, handed over with the project.
-
Apache
For hosting environments and legacy deployments already standardised on the Apache stack.
-
AWS
S3 for storage, CloudFront for delivery and EC2 or Lightsail for compute when a project needs room to grow.
-
Vercel
Preview deployments and edge hosting for Next.js and static frontends, live on every pull request.
-
Netlify
Simple static hosting with instant rollbacks for marketing sites and documentation.
-
Firebase Hosting
Fast global hosting for web apps that already use Firebase for auth, storage or notifications.
-
Heroku
Managed hosting for prototypes and early stage products that need to exist before they need to be tuned.
Why these tools
Every tool here had to earn its place
Nothing on this page is here because it is fashionable or because it looks good on a CV. Each one was measured against what happens after launch: who can maintain it, what it costs to host, and how quickly someone else could pick your project up if you stopped working with us.
The rules behind the list
A stack chosen for the client project or product
It is easy to pick tools that are fun to write and hard to inherit. Everything on this page had to pass four tests before it was allowed near a client project.
What goes in
- Your product idea
- A fixed budget
- A deadline that matters
What comes out
- An app on both stores
- Code in your accounts
- A team that can take over
Boring where it counts
The database, the auth layer and the deployment path are the last places to be clever. Proven tools there buy you the freedom to be interesting in the product itself.
Hireable, not exotic
Everything here has a large talent pool. When you eventually bring the work in house, you should be able to hire for the stack in a week, not a quarter.
No lock in by accident
Hosting, repositories and store accounts are created in your name from day one. If we stop working together, nothing has to be migrated out of our accounts.
Fast on a cheap phone
Performance targets are set against mid range Android hardware on a slow connection, because that is what most of your users are actually holding.
From our machine to your users
The path every change takes
Nothing reaches production by being copied onto a server. Every change walks the same five steps, which is why a release is a scheduled event rather than a late night with the lights on.
-
01
Local
Docker compose brings the whole stack up on one command. Seeded data means a new machine can run the full app in minutes.
-
02
Pull request
Static analysis, code style and the test suite run on every push. A red branch cannot be merged, no exceptions for deadlines.
-
03
Staging
Every merge deploys automatically to a staging URL with production like data, so you review real screens rather than screenshots.
-
04
Production
Tagged releases deploy with zero downtime. Migrations run first, caches warm, and a rollback is one command away.
-
05
Watch
Crash reporting, uptime checks and error alerts route to us. Most issues get seen and fixed before anyone thinks to report them.
How we choose
When two good options both look reasonable
These are the questions that decide the shape of a project, answered the same way here as they would be on a call, including the parts that are less convenient.
-
The question
KMP or native?
The call, and why
Kotlin Multiplatform, unless the product is defined by platform features.
For most apps sharing the business logic, networking and data layers through Kotlin Multiplatform cuts the build cost and keeps both platforms in step forever after, while each one still gets a fully native interface rather than a compromise UI. The moment a product depends on deep platform integration, widgets, background location, or heavy media processing, the maths flips and going fully native becomes the cheaper option over the life of the app. That decision gets made in the first call, with the reasoning explained, not defaulted to whatever we feel like writing.
-
The question
Laravel or a JavaScript backend?
The call, and why
Laravel, almost always.
Queues, scheduled jobs, file storage, database migrations, mail, authentication and an admin layer all come as first party pieces that are designed to work together. That removes a dozen small integration decisions from every project, and it means the codebase you inherit looks like the documentation instead of one person taste. Node earns its place for realtime services and websocket work, running alongside rather than instead.
-
The question
MySQL or PostgreSQL?
The call, and why
MySQL by default, PostgreSQL when the data is interesting.
Both are excellent and both will outlive your product. MySQL wins on hosting availability and on how many people can operate it confidently at three in the morning. PostgreSQL wins the moment you need JSON columns you actually query, geospatial features, or constraints strict enough to stop bad data at the door rather than in application code.
-
The question
Managed hosting or your own server?
The call, and why
Managed at first, your own once the bill justifies it.
Early on, a managed platform costs less than the hours it would take to run your own infrastructure properly. Once traffic is predictable and the monthly bill has real weight, moving to a tuned server with Docker and Nginx often cuts hosting cost by more than half. The migration path is planned from the start so it is a scheduled task rather than an emergency.
-
The question
Do you use AI tooling?
The call, and why
Yes, for speed. Never for judgement.
AI assistance is genuinely useful for scaffolding, test fixtures, migrations and translating between languages. It is not trusted with architecture, security boundaries or anything touching payments and personal data. Every line that ships is read, understood and defended by a person, because that is what you are actually paying for.
| The question | The call, and why |
|---|---|
| KMP or native? | Kotlin Multiplatform, unless the product is defined by platform features. For most apps sharing the business logic, networking and data layers through Kotlin Multiplatform cuts the build cost and keeps both platforms in step forever after, while each one still gets a fully native interface rather than a compromise UI. The moment a product depends on deep platform integration, widgets, background location, or heavy media processing, the maths flips and going fully native becomes the cheaper option over the life of the app. That decision gets made in the first call, with the reasoning explained, not defaulted to whatever we feel like writing. |
| Laravel or a JavaScript backend? | Laravel, almost always. Queues, scheduled jobs, file storage, database migrations, mail, authentication and an admin layer all come as first party pieces that are designed to work together. That removes a dozen small integration decisions from every project, and it means the codebase you inherit looks like the documentation instead of one person taste. Node earns its place for realtime services and websocket work, running alongside rather than instead. |
| MySQL or PostgreSQL? | MySQL by default, PostgreSQL when the data is interesting. Both are excellent and both will outlive your product. MySQL wins on hosting availability and on how many people can operate it confidently at three in the morning. PostgreSQL wins the moment you need JSON columns you actually query, geospatial features, or constraints strict enough to stop bad data at the door rather than in application code. |
| Managed hosting or your own server? | Managed at first, your own once the bill justifies it. Early on, a managed platform costs less than the hours it would take to run your own infrastructure properly. Once traffic is predictable and the monthly bill has real weight, moving to a tuned server with Docker and Nginx often cuts hosting cost by more than half. The migration path is planned from the start so it is a scheduled task rather than an emergency. |
| Do you use AI tooling? | Yes, for speed. Never for judgement. AI assistance is genuinely useful for scaffolding, test fixtures, migrations and translating between languages. It is not trusted with architecture, security boundaries or anything touching payments and personal data. Every line that ships is read, understood and defended by a person, because that is what you are actually paying for. |
Common questions
Questions about the stack
What clients ask once they realise the tools are a decision someone made on their behalf.
-
Why hire an app developer instead of a large agency?
You get one accountable person who wrote the code, knows the reasoning behind every tool on this page, and can be reached directly instead of routed through account managers. An app developer for hire keeps the overhead an agency carries out of your budget, and puts it into the build instead.
-
Can you work inside our existing stack instead?
Usually yes. If your team already runs Django, Rails, .NET or a React Native app, we can work in it. What we will not do is quietly rewrite a working system to match our preferences. We audit first, tell you what is worth keeping, and only propose a change when the cost of staying is clearly higher.
-
Who owns the code and the accounts?
You do, from the first commit. Repositories, hosting, domain, store listings and third party services are created under your ownership with us added as a collaborator. Removing our access at the end of a project takes a couple of clicks and breaks nothing.
-
What happens when a framework releases a major version?
Upgrades are planned, not chased. We stay one version behind the bleeding edge for production work, then schedule the upgrade once the ecosystem has caught up. Security patches are a different matter and get applied straight away.
-
Do you write tests, or is that extra?
Tests for business logic, payments and anything touching user data are part of the build, not a line item. Full end to end coverage across every screen is scoped separately because it is genuinely more work and not every project needs it.
-
How do you hand a project over?
A PDF documentation file covering how to get the project running locally, an API collection, and an architecture note explaining the non obvious decisions, delivered together with the full project sources. The goal is that the next person does not need us.
-
Will my app still build in two years?
Dependencies are pinned, the build is containerised and the CI configuration lives in the repository. That combination is the difference between an app that rebuilds cleanly years later and one that needs an archaeology session first.
-
Is this stack the same whether I hire an app developer for a small project or a full product?
The list of available tools is the same either way. What changes is how much of it gets used. A small project might only touch Kotlin Multiplatform, Laravel and MySQL. A full product pulls in queues, caching, CI and a proper deployment pipeline from day one. Nothing here is oversized for a small hire on purpose.
Always evolving
This page will look different next year
Technology keeps moving, and so does this list. New tools get tried on our own projects long before they are recommended for yours, and anything that stops earning its place quietly comes off the page. If you want to know whether something specific fits your project, ask directly and you will get a straight answer rather than a sales one.