HTML, CSS, JavaScript, PHP, Python, Django, Node.js, MySQL, PostgreSQL, Git, GitHub, Leytewebhost VPS, WP Engine, Cloudflare. That's the technical core of how we build and ship products. No unnecessary abstraction layers, no infrastructure that takes a dedicated engineer to run. Just languages and servers that do exactly what the project needs.
Every team makes stack decisions, often early in a project when the full scope isn't clear yet. We've learned to pick technologies based on what the product actually requires rather than what's trending. The result is a set of choices we can defend line by line and hand off to any competent developer without a three-hour onboarding session.
This is what we actually run, why we run it, and where we draw the line on complexity.
"Pick the language that solves the problem. Not the one that sounds good in a job post."
Languages and Runtimes
Our language choices follow the project type. We are not a single-language shop, but we keep the list short and we know each one deeply.
The foundation of every frontend we ship. HTML5 for semantic structure, CSS3 with custom properties and Grid for layout, and vanilla JavaScript for interactivity. No transpilation, no bundler required for most projects. The browser parses it directly and it runs everywhere without a build step.
We use vanilla JS for DOM manipulation, fetch for API calls, and the Intersection Observer API for scroll behaviour. When a project genuinely needs a framework, we reach for one. Most marketing sites, landing pages, and content builds don't. A 40kb JavaScript bundle to render a static about page is a problem we don't create.
PHP 8 is our server-side language for WordPress builds and custom backend logic. Modern PHP is fast, well-typed, and runs on virtually every hosting provider without configuration. We write custom WordPress themes and plugins in PHP, using hooks, filters, and the WP REST API to extend WordPress beyond its defaults.
PHP 8 specifically brings named arguments, match expressions, union types, and fibers | features that make the codebase substantially cleaner than legacy PHP. We run PHP 8.2 minimum on all WordPress projects and enforce strict types throughout custom code.
Node.js handles our custom API builds, backend services, and server-side rendering when the project needs it. We use Express for lightweight REST APIs and Next.js when a project requires server-side rendering with React on the frontend. Node runs well on serverless platforms and scales horizontally without much configuration.
For data-heavy apps with complex business logic, we use TypeScript on top of Node. It catches the category of runtime error that shows up in production on plain JavaScript and makes large codebases significantly easier to refactor. We don't reach for TypeScript on every project but it earns its place when the codebase grows past a few hundred lines.
Django is our primary backend framework for Python projects. It is batteries-included by design: ORM, authentication, admin panel, migrations, form handling, and a security layer all come built in. When we need to ship a full-featured web application backend fast, Django removes the boilerplate and lets us focus on the product logic itself.
We use Django REST Framework on top of Django to build RESTful APIs that front-end clients and mobile apps consume. The combination is particularly strong for data-heavy applications: Django's ORM handles complex queries well, the admin panel gives clients a functional back-office on day one, and the migration system keeps the database schema versioned alongside the application code.
For lightweight microservices and AI feature backends where we don't need the full Django stack, we use FastAPI. It handles high-throughput endpoints cleanly and plays well alongside a Django main application when the two need to run as separate services.
Databases
Database choice comes down to the shape of the data and the access patterns. We don't default to a single database for every project. We pick based on what the data actually looks like.
MySQL is the database under every WordPress installation. It's also our choice for any project with structured, relational data where the schema is well-defined upfront. WordPress runs on MySQL 8 and the performance difference from older versions is significant enough that we enforce it on every managed hosting setup we configure.
We write custom SQL queries for complex reporting features rather than layering an ORM over everything. Direct queries are faster, easier to debug, and don't add a dependency that can break on a version update. For simpler CRUD operations inside WordPress plugins, we use wpdb with prepared statements to prevent SQL injection.
PostgreSQL is our primary database for all custom application backends. It pairs directly with Django through psycopg2 and Django's built-in ORM, which means schema migrations, model relationships, and query generation are all handled through the application layer without writing raw SQL for standard operations.
Where PostgreSQL really earns its place over other databases is in advanced workloads. Full-text search with pg_trgm means we can add search to a Django app without pulling in Elasticsearch. JSONB columns let us store flexible, schema-less data inside a relational table and still run indexed queries against it. Window functions and CTEs make complex reporting queries possible directly in the database rather than in Python code.
Django's migration framework keeps every schema change versioned in the repository alongside the application code. No manual ALTER TABLE on production, no undocumented schema drift between environments. The staging database runs the same migrations before anything reaches live.
Infrastructure and Hosting
Where the code runs matters as much as how it's written. We match the hosting infrastructure to the project type rather than defaulting everything to the same provider.
Leytewebhost VPS is our primary hosting infrastructure for all client projects. Every site, application, and backend service we deploy lives on a VPS instance, giving us full root access to the server environment. We configure NGINX as the web server and reverse proxy, set up SSL certificates via Let's Encrypt, manage firewall rules with UFW, and tune PHP-FPM or Node process management depending on what the project runs.
The VPS model means we control the full stack from the OS up. We partition resources across projects, isolate environments per client, and scale vertically when a project grows. Deployments go through GitHub Actions, which SSH into the server, pulls the latest code, runs any pending migrations, and restarts the relevant services. No platform lock-in, no surprise pricing tiers, and no features hidden behind an enterprise plan.
WordPress installations go on WP Engine. Managed WordPress hosting means PHP version management, automatic core updates, server-level caching, daily backups, and a staging environment are all handled by the platform. We don't maintain the server. We maintain the application.
WP Engine runs PHP on servers tuned specifically for WordPress workloads. The built-in EverCache layer handles full-page caching without a plugin, which keeps the plugin count lower and eliminates a common performance bottleneck. Clients get SSH access, SFTP, and a one-click staging environment where we test updates before pushing to production.
When a project needs a real server, we use DigitalOcean Droplets or App Platform. Node.js APIs, Python backend services, and PostgreSQL databases that need persistent connections run on DigitalOcean. It's more predictable to price than AWS for the workloads we handle, and the managed database service removes the operational burden of running Postgres ourselves.
We run NGINX as a reverse proxy in front of Node processes, use PM2 for process management, and configure UFW for firewall rules. Deployments go through GitHub Actions: tests run on push, and on merge to main a deploy script SSH's into the Droplet, pulls the latest code, runs migrations, and restarts the process. Zero downtime deploys for low-traffic apps, blue-green for anything critical.
Every domain we manage points through Cloudflare. DNS propagates in seconds instead of hours. The proxy sits in front of every origin and handles DDoS mitigation, bot filtering, SSL termination, and HTTP/3 without any configuration from us. The free tier covers everything most projects need.
Cloudflare's cache rules let us set fine-grained TTLs on static assets independently from HTML responses. Images and fonts get long cache times. HTML gets a short TTL so content changes show up quickly. Page Rules and Transform Rules handle redirects and header injection at the edge without touching application code.
Version Control and CI/CD
Everything lives in Git. Every project gets a GitHub repository on day one, before a single line of code is written. Branches for features, pull requests for review, main for production.
GitHub Actions runs our CI pipelines. On every pull request: lint, type check, and unit tests run automatically. Nothing merges with a failing check. On merge to main, the deployment pipeline fires. For all projects hosted on Leytewebhost VPS, the workflow SSH's into the server, pulls the latest code, runs migrations, and restarts services in order. For WordPress, it syncs the theme to the staging environment on WP Engine via SSH before going live.
- Git feature branches with short lifespans
- GitHub Actions for all CI and deployment pipelines
- Semantic versioning for plugins and packages we publish
- Environment variables for all secrets and credentials
- npm for JavaScript package management
- Composer for PHP dependency management
- Long-lived feature branches that cause painful merges
- Secrets committed to any repository, ever
- Multiple CI systems on the same project
- Deploying directly from a local machine to production
- Skipping code review for hotfixes under time pressure
- Docker on projects that don't need container isolation
"If it's not in Git, it doesn't exist. If it deployed from a local machine, it's already a problem."
When the Stack Changes
The stack above covers the majority of what we build. But every project is assessed on its own requirements. Here's how the technology decisions actually get made.
A static marketing site gets HTML, CSS, JS, and a Leytewebhost VPS instance running NGINX to serve the files. No database, no application runtime, no PHP. The fastest possible architecture for a site that doesn't need dynamic data.
A WordPress build adds PHP 8, MySQL, and WP Engine. The language choice is PHP because that's what WordPress runs on and there's no benefit in abstracting it. The hosting choice is managed because we don't want to babysit a LEMP stack for a CMS project.
A custom web application uses Python and Django on the backend, PostgreSQL as the database, DigitalOcean for hosting, and GitHub Actions for CI/CD. Django's built-in ORM manages the PostgreSQL schema through migrations, and Django REST Framework exposes the API layer that any frontend or mobile client consumes. When the project has AI or data processing features, those live in a FastAPI microservice alongside the main Django application sharing the same PostgreSQL instance.
Four Rules We Don't Break
No secrets in the codebase
API keys, database passwords, and credentials live in environment variables on the server or in the CI secrets store. Not in .env files committed to the repo, not in comments, not hardcoded anywhere. One leaked key in a public repo is a significant incident.
Every database gets a migration file
Schema changes go into migration files versioned in Git alongside the application code. We never alter a production database schema by hand. If it can't be replayed from scratch on a clean database, it doesn't count as documented.
Staging before production, always
Every project has a staging environment that mirrors production as closely as possible. Plugin updates, theme changes, and backend deployments go to staging first. If it breaks on staging, it never reaches the client's live site.
Add infrastructure when the project earns it
A Redis cache, a message queue, a CDN layer: each one adds operational overhead. We add those components when the project genuinely needs them, not because the architecture diagram looks more impressive with them in it.
The Full Technical Stack at a Glance
- Frontend: HTML5, CSS3, Vanilla JS, React / Next.js for complex apps
- Backend: PHP 8.2 for WordPress, Python 3.12 + Django 5 for custom web apps and APIs, Node.js 20 LTS for JavaScript-heavy services, FastAPI for AI microservices
- Databases: PostgreSQL 16 as the primary database for all Django apps (psycopg2, Django ORM, migrations), MySQL 8 for WordPress
- Hosting: Leytewebhost VPS (static sites and custom apps via NGINX), WP Engine (managed WordPress)
- Infrastructure: Cloudflare for DNS, CDN, and DDoS protection on all projects
- CI/CD: GitHub Actions for automated testing and deployment pipelines
- Version control: Git with GitHub, feature branches, pull request reviews required before merge
The Bottom Line
The technologies above are not the most cutting-edge choices available. They're the ones we know well enough to move fast with, debug quickly, and hand off cleanly. A team that knows PHP 8 and MySQL deeply ships more reliable WordPress work than a team that knows them superficially and reaches for a trendy abstraction on top.
Every technology in this list has been in production under real load. We know where each one breaks and how to fix it. That knowledge, more than the choice of technology itself, is what actually keeps projects moving without breaking things.