Why I stopped using feature flags as configuration and started treating them as code
Feature flags stored in external systems create deployment coupling and make debugging production issues nearly impossible.
Writing about AI-assisted development, software engineering, and personal projects.
Feature flags stored in external systems create deployment coupling and make debugging production issues nearly impossible.
useEffect cleanup functions create memory leaks and race conditions when you don't understand React's rendering lifecycle.
AI coding assistants excel at boilerplate and patterns, but they create subtle bugs in complex business rules that are expensive to fix.
Git hooks seem perfect for enforcing code standards, but they create inconsistent environments and frustrating developer experiences.
Vite's dev server is blazing fast for frontend builds, but proxying API requests creates debugging nightmares and deployment mismatches.
useState handles synchronous state perfectly, but async operations need proper loading states, error handling, and race condition prevention.
useContext seems perfect for sharing state, but it causes unnecessary re-renders and makes component testing nearly impossible.
useRef seems like the obvious choice for DOM access, but callback refs handle dynamic elements and cleanup automatically.
useState seems natural for API data, but it creates stale state bugs and makes caching impossible.
useCallback seems like a performance optimization, but overusing it actually makes your app slower and harder to maintain.
useEffect seems like the right place for error handling, but it creates unpredictable error states and makes debugging a nightmare.
useState feels natural for forms, but it creates a tangled mess of validation logic that's hard to test and maintain.
Accepting Copilot's first suggestion feels productive, but it often leads to technical debt and missed learning opportunities.
Environment variables seem like the obvious choice for feature flags, but they create deployment headaches and limit runtime flexibility.
Prettier's defaults work for most teams, but customizing key rules improved my code readability and Git diffs.
React.memo() feels like free performance, but it often creates more problems than it solves.
React Hook Form and controlled components solve different problems -- here's when to use each approach.
Native tooling and package managers are faster and more reliable than containerizing every development dependency.
Structured logging with proper levels and context makes debugging production issues infinitely easier than scattered console.log statements.
Interfaces provide better extensibility and clearer intent than type aliases when designing public APIs and component props.
Traditional integration tests miss the forest for the trees -- testing user flows catches real bugs that matter to your users.
Modern data fetching patterns with React Query and SWR eliminate most useEffect complexity while providing better user experience.
How I use AI to quickly identify root causes and generate fixes for production bugs without panic-driven debugging.
AI pair programming generates better test cases faster than traditional TDD, while still maintaining code quality and coverage.
Node.js 18's built-in test runner eliminates dependencies and simplifies testing without sacrificing functionality.
Building your own tools first teaches you the problem domain and often leads to simpler, more maintainable solutions.
Why complex dev setups often hurt productivity more than they help, and how I learned to embrace boring tools.
Switching to pnpm and Corepack improved my development workflow, disk usage, and dependency management across projects.
Why I switched from plain markdown to MDX and never looked back -- interactive examples and component reuse changed everything.
My self-review workflow using Claude to catch bugs and improve code quality before my teammates even see it.
Building a complete deployment pipeline for Cloudflare Workers using GitHub Actions and Wrangler CLI.
The TypeScript utility types, discriminated unions, and branded types that make my code cleaner and safer in production.
Why I built rjemerson.com with Next.js 15, MDX, and Cloudflare Workers — and what I learned along the way.
What I learned integrating AI coding agents into my daily workflow and how it changed the way I think about software architecture.
A deep dive into setting up local language models for code generation, review, and testing.
Comparing deployment platforms for Next.js applications. Costs, cold starts, edge compute, and DX.