Skip to content

Principles

The seven I enforce, in the order I use them.

1. First make it work, then make it right, then make it better

Kent Beck’s rule — his version ends “make it fast,” but for most product code, cleaner and easier to change matters more than raw speed, so I’ve swapped the third. Same discipline: in that order, not simultaneously. A working ugly PR ships; an elegant unfinished one doesn’t. Refactoring lands in its own PR, after the behavior change is merged and green.

2. Small commits, small PRs, merged often

A 40-file PR is not thorough — it’s a review-blocker and a rollback liability. If your change genuinely touches 40 files, split by concern and stack the PRs. The reviewer’s time is more expensive than yours.

3. Every push leaves main green

CI red on main is a team-wide interruption. If your PR merges red, your next task is fixing it — not the ticket you were about to pick up. Green-on-main is a shared asset; you don’t spend it on your own convenience.

4. Own your PR from open to prod

Opening the PR is the first 20% of the work. Following up on review comments, watching CI, monitoring the deploy, checking logs the next morning — that’s the other 80%. If you merge and disappear, someone else has to babysit your code. That someone is now doing your job.

5. Prevent bugs with systems, not with QA

Types catch a class of bugs. Component boundaries catch another. Automated tests, staging environments, and CI gates catch more. QA catches what all of that missed — which should be a small, decreasing set. Every time QA finds a bug that a type or a test could have caught, that’s a system to add, not a bug to fix. More on this shape of thinking in code review.

6. Design from the product, not from the framework

I’ve never architected a system by asking “what does Next.js want here?” I ask what the customer is doing, what the operator is doing, what happens when a payment fails at 2am. The framework should serve those questions — when it starts dictating them, it’s usually the wrong framework for the problem.

7. Modernize without rewriting

The rewrite is almost always the wrong answer. It’s ambitious, it feels brave, and it kills more startups than any bug ever has. The right answer is usually to keep shipping the current system while migrating route by route, behind a flag, with tests.

GoDiligent’s modernization was roughly 50 PRs — React 16 → 18 and Pages Router → App Router — done incrementally, route by route, with the old and new stacks running side-by-side until each screen was cut over. Feature work never stopped for a freeze. That’s the migration pattern I’d defend to a CEO every time: slower on paper, faster in practice, dramatically less likely to blow up. This principle drives most of what’s in frontend architecture too.