Our Tech Stack Explained
When you hire a development team, you deserve to know what they're building with. Too many agencies keep their tech stack vague, either because they don't want to commit or because they piece together whatever seems easiest for each project.
We're going to be completely transparent. Here's exactly what we use and why we chose it.
Frontend: React and TypeScript
React is our UI library of choice. It's been around since 2013, powers some of the biggest sites on the internet (Facebook, Instagram, Netflix, Airbnb), and has a massive ecosystem of supporting tools.
We write all our React code in TypeScript rather than plain JavaScript. TypeScript adds static typing, which means we catch errors at compile time instead of discovering them when users hit bugs. It's a bit more work upfront but saves countless hours of debugging later.
The combination of React and TypeScript gives us:
- Component-based architecture that makes code reusable
- Type safety that prevents entire categories of bugs
- Excellent tooling and editor support
- A huge pool of developers who know these tools if you ever need to expand your team
Framework: Next.js
We covered this in depth in our previous post, but the short version: Next.js handles routing, server-side rendering, API routes, and deployment. It's the glue that holds everything together and gives us a proven architecture for any project.
Every project starts with npx create-next-app and builds from there. We don't reinvent the wheel.
Styling: Tailwind CSS
Tailwind CSS is a utility-first CSS framework. Instead of writing custom CSS classes, you apply small utility classes directly in your HTML. It sounds weird if you haven't tried it, but it's incredibly fast once you get used to it.
Example: instead of creating a .button-primary class and defining its styles elsewhere, you write className="bg-blue-500 text-white px-4 py-2 rounded" directly on the element.
Benefits we've found:
- No more naming things (harder than it sounds)
- No CSS files growing endlessly
- Consistent spacing and colors enforced by the system
- Responsive design is trivial. Just add
md:orlg:prefixes - Dark mode support is built in
For more complex components, we sometimes use shadcn/ui, which gives us beautifully designed, accessible components that we can customize completely.
Database: PostgreSQL via Supabase
When a project needs a database, we reach for Supabase. It's a backend-as-a-service that gives you a PostgreSQL database with a nice UI, automatic API generation, authentication, and storage.
Why PostgreSQL? It's the most capable open-source relational database. It handles everything from simple data storage to complex queries, full-text search, and even JSON documents. We've never hit a wall where PostgreSQL couldn't do what we needed.
Why Supabase specifically? A few reasons:
- Generous free tier for development and small projects
- Automatic REST and GraphQL APIs from your schema
- Built-in authentication that actually works
- Real-time subscriptions out of the box
- You own your data and can export anytime
For projects that don't need a full database, we might use something lighter. But Supabase is our default because it scales well and doesn't lock us in.
Authentication: Supabase Auth or NextAuth.js
User authentication is one of those things that seems simple but has a million edge cases. Password reset flows, email verification, session management, security headers - getting it wrong means security vulnerabilities.
We usually use Supabase's built-in auth when we're already using Supabase for the database. It handles email/password, magic links, and OAuth providers (Google, GitHub, etc.) with minimal setup.
When we need more flexibility or aren't using Supabase, NextAuth.js is our backup choice. It's specifically designed for Next.js and supports basically every authentication provider you can think of.
Hosting and Deployment: Vercel
Vercel is where most of our projects live. They build Next.js, so the integration is flawless. But beyond that, their platform is genuinely great:
- Deploy by pushing to GitHub. That's it.
- Every pull request gets its own preview URL
- Global CDN means fast load times everywhere
- Analytics and monitoring built in
- SSL certificates handled automatically
- Serverless functions for backend logic
For static sites that don't need serverless functions, we sometimes use Cloudflare Pages instead. It's faster for pure static hosting and the free tier is even more generous.
Version Control: Git and GitHub
Every line of code we write goes into Git, hosted on GitHub. This gives us:
- Complete history of every change ever made
- Easy collaboration between team members
- Code review through pull requests
- Automatic backups of everything
- Integration with deployment pipelines
When we hand over a project, you get full access to the repository. No vendor lock-in, no proprietary systems.
Other Tools We Reach For
Stripe - Payment processing. It's the standard for a reason. Great API, handles everything from one-time payments to subscriptions.
Resend - Transactional email. Clean API, good deliverability, reasonable pricing.
Cloudinary or Uploadcare - Image and file management. Handles uploads, transformations, and delivery.
Sentry - Error tracking. When something breaks in production, we know about it immediately.
PostHog or Plausible - Analytics. Privacy-friendly alternatives to Google Analytics.
What We Don't Use
Just as important as what we use is what we avoid:
- WordPress - Too slow, too many security patches, too hard to customize well
- Page builders - Wix, Squarespace, Webflow. Fine for DIY, but we can do better
- jQuery - Had its time, but React handles everything better now
- Bleeding-edge frameworks - We don't experiment on client projects
This stack has evolved over years of trial and error. It's not the only way to build things, but it's a proven combination that delivers results consistently. And that's what matters.