Files
zhaoguiyang.site/src/pages/blog/posts/2026010801.md
joyzhao 9f05776781
Some checks failed
Deploy docs for Site / deploy (20.x) (push) Has been cancelled
feat(blog): 更新博客文章元数据,添加阅读时间和分类信息
2026-01-09 12:10:37 +08:00

6.8 KiB
Raw Blame History

layout, title, description, date, image, tags, tagId, category, categoryId, readTime
layout title description date image tags tagId category categoryId readTime
@/layouts/BlogPostLayout.astro All This Tinkering... For What? Engineering Reflections from a Full-Stack Developer An honest reflection on tech stack selection paralysis. One developer's journey from chasing 'best practices' to realizing that technology is a tool, not a totem—how to avoid over-engineering and find the right fit for your actual needs. 2026-01-08 https://images.unsplash.com/photo-1518770660439-4636190af475?q=80&w=1470&auto=format&fit=crop
Reflections
Full-Stack
Engineering
Personal Reflection
reflections
fullstack
engineering
development-reflection
Engineering engineering 8 min read

A log of the soul-crushing details I encountered during a recent project setup. This is a summary of my own internal tug-of-war—lessons learned the hard way through endless trial and error. It might not be the "correct" way, but every word was paid for in lost time.

I recently set out to build a simple bookmarking tool. It only needed about 30 endpoints, yet I spent nearly a month agonizing over the tech stack. I felt like I was wandering through a dark forest, sprinting toward every glimmer of light only to find a new pitfall waiting for me.

Step 1: Chasing the "Mainstream" and Feeling the Friction

It started because I wanted to build a side project. In my day job, I use Vue; its second nature to me. But everywhere I looked online, the consensus was: "Next.js + React + shadcn-ui" is the gold standard. Great ecosystem, endless components, future-proof.

I told myself: Dont get stuck in your comfort zone. Try something new. So, I benched Vue and picked up React. I was immediately hit by choice paralysis.

It wasn't just a choice between A and B; it was a choice between five different ways to do everything. I spent more time reading docs and comparisons than writing logic:

  • Do I fetch data with SWR or TanStack Query?
  • Is global state better in Zustand, Redux, or Jotai?
  • How do I bridge the gap between server and client data?

Instead of building features, I was researching "how to build." To make matters worse, I kept hitting those cryptic "Hydration Errors." One refresh, one error, and an hour gone trying to find the mismatch.

The most draining part was tagging everything with "use client". I felt less like a developer and more like a clerk labeling boxes. I kept thinking: "If most of this ends up running on the client anyway, why am I using a framework that splits the stack so aggressively and demands such high mental overhead?"

Step 2: Retreating to Comfort—and the Fear of Missing Out

I went back to my familiar Vue ecosystem and fired up Nuxt. Suddenly, I could breathe. My productivity skyrocketed.

But the peace didn't last. Id see another post praising the Next.js ecosystem and start doubting myself: "Am I choosing the wrong path? Am I falling behind?" I gave Next.js another shot for a few days, and like clockwork, all those petty, nagging frustrations returned.

Thats when I realized: Tech isn't about "better" or "worse"; its about fit. Trust your "handfeel." That sense of flow (or lack thereof) doesn't lie.

Step 3: The "Professionalism" Trap

Once the frontend was settled, I moved to the backend. I chose NestJS because its billed as the most "Enterprise-grade" option. To make it even more "professional," I forced it into a Monorepo. I effectively built myself a prison:

  • Immense Friction: Changing a single shared enum or type meant re-building, waiting for workspace syncs, and restarting services. A 10-second change turned into a 1-minute wait.
  • Compatibility Hell: NestJS is still clinging to CommonJS. Trying to use a pure ESM library or running a TS Worker thread resulted in config errors that made me question my career choices.
  • Ceremony Over Substance: For 30 endpoints, I was writing endless Controllers, Services, Modules, and DTOs. The lines of code tripled, but the core logic stayed exactly the same.
  • The Swagger Tax: I wanted to use Zod for validation, but Swagger only recognizes decorators (class-validator). I ended up maintaining two nearly identical data definitions just to have an API doc.

I traded my immediate efficiency for the "advantages of a large team" that I don't actually have. I wanted speed; the framework demanded "maintainability" for a scale I'll likely never hit.

Step 4: Stripping it Down and Losing My Way

I ditched the heavy frameworks for Fastify, thinking Id keep it lean. But I quickly discovered that the problem wasn't just "weight"—it was "the anxiety of absolute freedom."

Fastify is liberating, but for someone used to structure, freedom is a burden:

  • "Where should this file go?"
  • "How do I organize this into a plugin?"
  • Logging, queues, auth—everything NestJS gave me for free now required me to find, integrate, and debug a third-party library.

I hated the rules of heavy frameworks, yet I craved their structure. My mindset was completely torn.

The Epiphany: Tech is a Tool, Not a Totem

One night, working late, I asked myself: "Why am I doing this? I just wanted to build a simple tool."

Everything clicked. I was applying "Long-term Enterprise Maintenance" standards to a "Solo Rapid Prototype." It was like trying to build an eight-lane highway just to go to the grocery store around the corner.

I set a new, simple rule for myself:

  1. For Prototypes & Small Tools: Use Nuxt (or a monolithic framework) exclusively. Frontend and backend in one repo, natural type synchronization, no CORS issues, no sync friction. The goal is to ship.
  2. For Complex Systems & Large Teams: Then consider Nuxt + NestJS + Monorepo. The complexity is a fair trade for the architectural guardrails.

A New Contender: AdonisJS

During this spiral, I stumbled upon AdonisJS. Its often called the "Laravel of Node.js." From a quick look, it seems to hit the sweet spot: it has the structure I crave (ORM and Auth built-in) but feels modern and supports ESM natively. I might give it a spin next time.

Final Thoughts

  1. Dont blind-follow the hype: What works for Vercel might not work for your weekend project.
  2. Trust your "handfeel": If a tool makes you feel productive, that's worth more than any "State of JS" ranking.
  3. Ship first, optimize later: For a solo project, an un-launched architecture is just expensive fan fiction.
  4. Watch out for "Config Friction": If you spend more time in .json and .config.js files than in your logic, your tools are failing you.

This was my journey through the weeds. My approach might be "wrong" or even a bit clumsy. Id love to hear how you handle the "stack anxiety." Do you have a go-to setup that just works, or are you still searching for the "perfect" balance?