How I think about engineering web systems.
A note on technical philosophy — what I reach for, what I avoid, and how engagements actually run. The day-to-day services live on the Web Systems page; this page is here for people who want to know how the practice thinks about technology before they engage.
Boring technology, honestly scoped.
How I approach custom software — and why the build is only half the engagement.
Most custom application projects go wrong in predictable ways. The scope expands until the project collapses. Or the system gets delivered as a black box that only the original developer can maintain. Or — most commonly — the system ships successfully, gets quietly deprioritized for six months, and by the time anyone looks at it again the dependencies have rotted, the SSL has lapsed on a subdomain no one was watching, and a plugin update three versions ago broke a form no one noticed.
All of these failure modes are avoidable with honest scoping, maintainable technical choices, and the understanding that building a system and keeping it running are two halves of the same engagement. I try to build things I can justify building. When an off-the-shelf tool will solve the problem, I’ll say so. When a spreadsheet is genuinely the right answer for now, I’ll say that too. When custom software is the right call, I scope against the smallest version that delivers the outcome — because most teams don’t need the application they think they need; they need the 30% of it that actually solves the problem.
My technical preferences lean toward boring, maintainable choices: PHP 8, JavaScript, React where it adds value, conventional database designs, documented APIs, deployments simple enough that your team can understand them. I avoid cleverness that becomes someone else’s maintenance burden. The goal is software that works reliably and can be understood by the next developer who touches it — including the future version of you.
What I reach for, what I avoid.
The choices behind how a typical project gets built.
What I reach for
- PHP, JavaScript, and React for most web-application work — mature ecosystems, easy to hire for, well-documented
- WordPress, headless CMS, or a purpose-built backend depending on what you actually need
- PostgreSQL or MySQL for relational data; flat files and caches where a database would be overkill
- Standard hosting: AWS, Google Cloud, or your existing environment — nothing exotic required
- REST APIs by default; GraphQL where the consumer genuinely benefits
What I avoid
- Bleeding-edge frameworks where stability isn’t proven — your system shouldn’t be someone else’s beta test
- Vendor lock-in without a clear exit path — I document how to migrate away, even as I build
- Clever abstractions that are faster to write than to read — the next maintainer will thank us
- “Low-code” platforms when the workflow is complex enough that you’ll outgrow them within 18 months
Accessibility, security, and AI — built in
Anything I build aims for accessibility considered from the start (WCAG 2.2 AA as a baseline), standard security headers and CSP, encrypted connections by default, and access controls appropriate to the data involved. For engagements touching PHI or regulated data, see the HIPAA page for additional detail. For AI-powered features inside a custom build, see AI.
What an engagement looks like.
A typical project build, week by week. Timelines vary with scope; a retainer-only engagement skips the first three steps.
-
Week 0
Discovery & scoping
We confirm the problem to be solved, the constraints (existing systems, integrations, compliance posture, budget), and the decision-makers on your side. You receive a fixed-fee proposal within a few business days.
-
Weeks 1–2
Architecture & prototype
A written architecture pass, a working prototype of the highest-risk piece, and a review session with your team. The natural checkpoint to adjust scope before most of the work gets built.
-
Weeks 3–N
Incremental build
Iterative delivery with weekly check-ins. I close features as I resolve them so you can verify progress, rather than receiving a single opaque push at the end.
-
Before launch
Review, documentation, handover
Accessibility check, security review, performance pass, documentation, and a walkthrough with whoever on your side will maintain or operate the system.
-
After launch
Retainer or handoff
Either a monthly retainer takes over for ongoing care, or I hand off cleanly to your internal team. In either case, you’re not left wondering what you have.
What you actually receive.
- Working software at each milestone, not just at the end
- Architecture documentation a successor developer can read
- API documentation where relevant (OpenAPI / Swagger format)
- Deployment runbook with the commands someone else could execute
- Environment setup that runs on a fresh laptop
- Credentials handover in a format your operations team expects
- Accessibility check against WCAG 2.2 AA on user-facing surfaces
- Security review (headers, CSP, access controls, dependency audit)
- Monitoring and alerting configured and documented
- For retainers: monthly summary of changes and issues handled
- For retainers: quarterly performance and accessibility re-check
Engineering, specifically.
Can you work with our existing codebase?
Yes, in most cases. I take on existing systems regularly — either to add features, fix issues, or take over maintenance. The first step is usually a short discovery pass to understand the code, the dependencies, the deployment setup, and whether there are any urgent risks that need immediate attention. If I conclude the system can’t be responsibly extended or maintained in its current shape, I’ll tell you plainly — and explain what a responsible path forward looks like.
Do you work with frameworks other than PHP and React?
Those are my defaults, not my limits. I’m comfortable in Node, Python, and a range of JavaScript frameworks (Vue, Svelte, plain JS when that’s the right call). I avoid picking up a stack I don’t know well for a production engagement — the learning curve would be on your dollar, which isn’t fair — but the core of the work is the same in any modern stack: clean data models, tested integrations, maintainable code.
What does a typical retainer cost?
Retainers are priced against scope, not hours — a small informational site is very different from a production application with user accounts and integrations. After a scoping conversation I propose a fixed monthly fee with clearly defined inclusions. Most retainers land in a predictable band, and I’m happy to talk ranges on the discovery call so you can tell whether the shape fits your budget before investing further time.
Will we own the code and the infrastructure?
Yes, always. I build in your repositories, on your cloud accounts, with credentials you control. You own the code, the data, and the infrastructure — and my documentation is designed so you could replace me tomorrow if you needed to. I’d rather earn the retainer by doing the work well than by making the system impossible for anyone else to maintain.
Can you add AI features to an existing application?
Yes — this is an increasingly common engagement. LLM-powered features, retrieval over existing content, AI-assisted intake, document classification. I treat AI features as first-class engineering concerns with the same rigor as the rest of the system: grounded in your data, evaluated before ship, logged and monitored. See the AI page for more detail.
What if our CMS is working against us?
Common and solvable. Sometimes the answer is configuration, sometimes a plugin swap, sometimes a headless re-architecture where the CMS serves content and a purpose-built frontend handles everything else. Occasionally the honest answer is that the CMS itself is wrong for what you’re trying to do, and I’ll say so — even when it means a larger conversation than you were hoping to have.
How do you handle urgent security issues?
Retainer clients have priority access for anything genuinely urgent — same business day response, treated as a drop-everything problem. For non-retainer clients I take on emergency engagements when capacity allows. For anything that might be a live exploit, take the public surface offline first and then call — I’d rather you be safe than polite about the process.
For the actual services.
Want to talk through a specific build?
Whether you’re scoping a new build, looking at a retainer for an existing system, inheriting a codebase, or just trying to decide what to build at all — a 30-minute conversation is the cleanest way to find out whether we’re a fit.
Book a 30-minute consultation
I’ll send a short set of questions beforehand so the call is useful from the first minute.