<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: xiu</title>
    <description>The latest articles on DEV Community by xiu (@xiunotes).</description>
    <link>https://dev.to/xiunotes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1072562%2F26b41132-5fb1-4e32-a589-268e39a87832.png</url>
      <title>DEV Community: xiu</title>
      <link>https://dev.to/xiunotes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xiunotes"/>
    <language>en</language>
    <item>
      <title>An AI-Ready NestJS + Next.js Boilerplate for 2026</title>
      <dc:creator>xiu</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:24:26 +0000</pubDate>
      <link>https://dev.to/xiunotes/an-ai-ready-nestjs-nextjs-boilerplate-for-2026-h4d</link>
      <guid>https://dev.to/xiunotes/an-ai-ready-nestjs-nextjs-boilerplate-for-2026-h4d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F754xw5zfpnalvytwwkio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F754xw5zfpnalvytwwkio.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a NestJS + Next.js monorepo I'd happily start any new SaaS on today. It's on &lt;a href="https://github.com/oNo500/nestjs-boilerplate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. The README covers what's in it. This post is about three decisions that shaped how it's organized, and why I think they'll hold up as AI assistants keep getting better at writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Drizzle, Base UI, oxlint
&lt;/h2&gt;

&lt;p&gt;The project uses Drizzle instead of Prisma, Base UI instead of Radix, and oxlint instead of ESLint. These aren't adventurous picks. They share one property: they reduce the number of things that can go wrong.&lt;/p&gt;

&lt;p&gt;Drizzle's schema is its type definition. You write &lt;code&gt;pgTable(...)&lt;/code&gt;, call &lt;code&gt;$inferSelect&lt;/code&gt;, and you have a typed row object. No code generation step, no separate schema format, no runtime engine. When a column changes, I rebuild the database package and every consumer sees the new type. Prisma is excellent, but it asks you to maintain a parallel schema language. I'd rather have one.&lt;/p&gt;

&lt;p&gt;Base UI replaces Radix's &lt;code&gt;asChild&lt;/code&gt; with an explicit &lt;code&gt;render&lt;/code&gt; prop. &lt;code&gt;asChild&lt;/code&gt; is powerful, but forgetting it silently renders nested &lt;code&gt;&amp;lt;button&amp;gt;&amp;lt;button&amp;gt;&lt;/code&gt; and nothing warns you. Base UI's approach is impossible to forget because the element you're rendering is right there in the prop. Less magic, fewer ways to be wrong.&lt;/p&gt;

&lt;p&gt;oxlint is a Rust-based linter that runs roughly an order of magnitude faster than ESLint on TypeScript. In a monorepo where &lt;code&gt;turbo lint&lt;/code&gt; runs on every branch, that's the difference between a CI step you notice and one you don't. The rule catalog is still catching up — for a few niche plugins I might keep ESLint around — but the direction of the toolchain is clear.&lt;/p&gt;

&lt;p&gt;These are the kinds of choices that matter more the longer you're going to live with the project. For a weekend prototype, picking the popular thing is fine. For a codebase I expect to maintain for years, I'd rather pay a small learning cost upfront for tools that stay out of my way.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Start simple, grow when the problem demands it
&lt;/h2&gt;

&lt;p&gt;When you start a feature, you rarely know which parts will matter. You don't know if the thing will have concurrent edits, or a state machine, or invariants that span fields. You find out by building it and watching what hurts.&lt;/p&gt;

&lt;p&gt;Most boilerplates force you to commit before you know. They scaffold repository + service + domain + event bus for every module and expect you to fill them in whether you need them or not. If you later figure out that this module is just CRUD, it's too late — the layers are there, deleting them feels like regression, and they stay. The code runs through abstractions that solve problems it doesn't have.&lt;/p&gt;

&lt;p&gt;I wanted a project that let me start cheap and add structure only when the problem demanded it. The repo has three example modules along that path.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;todo&lt;/code&gt; module is a plain service over a repository. Three files, no layers, no events. A todo has a title and a boolean; if the problem ever grew beyond that, this module would be easy to throw away or rewrite. It hasn't grown, so it stayed simple.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;article&lt;/code&gt; module is what happens when a CRUD module starts having rules — titles that can't be empty, slugs that need to match a pattern. A light business layer with value objects appears, not because I planned it upfront but because those rules kept leaking into the service. Extracting them was the cheapest way to keep the service honest.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;order&lt;/code&gt; module is what happens when the problem actually calls for the full toolkit. Orders have state transitions that must be validated (&lt;code&gt;draft → paid → shipped → cancelled&lt;/code&gt;). They have invariants that span fields — you can't pay twice with different amounts. They have concurrent edits that need optimistic locking. At that point an aggregate with value objects, domain events, and a version field isn't ceremony; each piece is solving something real. Take any of them away and something breaks.&lt;/p&gt;

&lt;p&gt;The three modules aren't three competing styles. They're the same module type at three stages of the same path: start with the smallest thing that works, grow the structure when the problem forces you to. A new contributor reading the repo sees this shape. When they notice a &lt;code&gt;domain/&lt;/code&gt; directory, it tells them this module has real invariants and to read the aggregate first. When they don't, it tells them the module is still in the simple stage, and the right move is to keep it that way as long as they can.&lt;/p&gt;

&lt;p&gt;This is the pattern I want a boilerplate to teach: not every pattern you might need, but when each one earns its weight.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The rules live with the code
&lt;/h2&gt;

&lt;p&gt;AI coding tools got good fast. On a typical day I let Claude or Cursor implement whole features while I watch, guiding the parts that need judgment. The collaboration works well.&lt;/p&gt;

&lt;p&gt;But any single session only sees the immediate problem. It doesn't know the long-term shape I'm committed to — which patterns are load-bearing, which boundaries I'm protecting, which trade-offs I made three weeks ago for reasons I haven't re-explained today. Retyping that context every conversation is exhausting, and I'd forget half of it under pressure anyway.&lt;/p&gt;

&lt;p&gt;So the project has a &lt;code&gt;.claude/rules/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/rules/
├── constitution.md         # project-wide principles
├── api.md                  # paths: apps/api/**
├── admin-shadcn.md         # paths: apps/admin-shadcn/**
├── database.md             # paths: packages/database/**
└── api-test.md             # paths: apps/api/**/*.spec.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file has a &lt;code&gt;paths:&lt;/code&gt; frontmatter declaration. When I edit something under &lt;code&gt;apps/api/&lt;/code&gt;, Claude Code auto-loads &lt;code&gt;api.md&lt;/code&gt;. Schema change? &lt;code&gt;database.md&lt;/code&gt; loads. Mechanically these are AI context files — the content gets injected into the conversation so the assistant has the project's long-term view without me pasting it in each time.&lt;/p&gt;

&lt;p&gt;What makes them worth their weight is that they're written so humans can read them too. Layer responsibilities, context boundaries, naming conventions — the things I'd explain to a new contributor on day one live in the same files the AI consumes. One source of truth, two audiences, nothing to keep in sync.&lt;/p&gt;

&lt;p&gt;Without this setup I'd still use AI tools, and code would still get written. But the project's shape would drift toward the AI's defaults — reasonable choices in isolation, stacked into something I wouldn't have designed. The rules are how my long-term thinking stays present in a project that's being written partly by someone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually get
&lt;/h2&gt;

&lt;p&gt;Cloning the repo gets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auth &amp;amp; RBAC&lt;/strong&gt; — JWT with Google and GitHub OAuth, role-based guards on the backend, role-aware components (&lt;code&gt;&amp;lt;RequireRole&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ShowForRole&amp;gt;&lt;/code&gt;) on the frontend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durable writes&lt;/strong&gt; — Idempotency-Key support with SHA-256 body hashing, ETag and If-Match for optimistic locking, RFC 9457 problem details for every error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-end types&lt;/strong&gt; — Drizzle drives database types; OpenAPI drives frontend hooks via &lt;code&gt;openapi-react-query&lt;/code&gt;. Change a column, rebuild the package, TypeScript flags every broken consumer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit logging&lt;/strong&gt; — every sensitive write emits a domain event the audit-log module picks up. No decorators sprinkled across controllers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin frontend&lt;/strong&gt; — Next.js App Router, TanStack Query, React Hook Form with Zod, shadcn/ui on Base UI, Tailwind v4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural rules&lt;/strong&gt; — five markdown files documenting the shape of the project, readable by humans and by the AI editing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a working skeleton, not a tutorial.&lt;/p&gt;

&lt;p&gt;Full source is on &lt;a href="https://github.com/oNo500/nestjs-boilerplate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, with deeper write-ups on &lt;a href="https://github.com/oNo500/nestjs-boilerplate/blob/master/docs/architecture.md" rel="noopener noreferrer"&gt;architecture&lt;/a&gt;, &lt;a href="https://github.com/oNo500/nestjs-boilerplate/blob/master/docs/api-conventions.md" rel="noopener noreferrer"&gt;API conventions&lt;/a&gt;, and &lt;a href="https://github.com/oNo500/nestjs-boilerplate/blob/master/docs/technology-choices.md" rel="noopener noreferrer"&gt;technology choices&lt;/a&gt;. If any of this lands wrong — or if you've tried something similar and it went sideways — I'd like to hear about it.&lt;/p&gt;

</description>
      <category>turborepo</category>
      <category>nestjs</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>2025 NestJS + React 19 + Drizzle ORM + Turborepo Architecture Decision Record</title>
      <dc:creator>xiu</dc:creator>
      <pubDate>Fri, 20 Jun 2025 04:16:44 +0000</pubDate>
      <link>https://dev.to/xiunotes/2025-nestjs-react-19-drizzle-orm-turborepo-architecture-decision-record-3o1k</link>
      <guid>https://dev.to/xiunotes/2025-nestjs-react-19-drizzle-orm-turborepo-architecture-decision-record-3o1k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wiattctb555rkjhlph2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wiattctb555rkjhlph2.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This document mainly records my thought process behind the technical architecture selection for a full-stack application, along with practical implementation summaries, to serve as a long-term reference for full-stack projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There won’t be tedious code examples here — for details, check the project directly&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
👉 Project: &lt;a href="https://github.com/oNo500/nestjs-boilerplate" rel="noopener noreferrer"&gt;nestjs-boilerplate&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Positioning
&lt;/h2&gt;

&lt;p&gt;Before making any technical choices, it’s important to clarify what this project aims to achieve.&lt;/p&gt;

&lt;p&gt;In my daily development, I often take on small projects. Usually, it’s quick to scaffold something with any framework, but it inevitably involves tedious configuration and toolchain integration. Since these projects are small in scope with limited decision time, technical choices and integration workflows are often passive — just “use whatever works”. As a result, there’s little opportunity for meaningful accumulation, and a lot of time is wasted on redundant setups.&lt;/p&gt;

&lt;p&gt;To improve this, I want to prepare a complete, full-stack tech stack in advance. It should allow me to quickly set up projects, while also offering a solid base for diving deeper into vertical project structures and implementation details — instead of repeatedly wasting time on “horizontal selection” each time. This should boost development efficiency and help accumulate reusable experiences and best practices for future projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Positioning:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full-stack application covering frontend, backend, utility libraries, and UI component libraries&lt;/li&gt;
&lt;li&gt;Suitable for individual developers handling both frontend and backend&lt;/li&gt;
&lt;li&gt;Supports fast MVP prototyping&lt;/li&gt;
&lt;li&gt;Emphasizes maintainability and extensibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech Stack Selection Criteria
&lt;/h2&gt;

&lt;p&gt;Given the vast JavaScript ecosystem and abundant options, I primarily consider the following factors when choosing technologies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Stars&lt;/strong&gt;
Prioritize projects with high star counts and active maintenance. Exclude those with high stars but no recent activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPM Downloads&lt;/strong&gt;
High download counts → indicates popularity and a lively community where issues are quickly resolved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Support&lt;/strong&gt;
Must fully support TypeScript to ensure type safety and offer a good developer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Adaptability&lt;/strong&gt;
Should flexibly adapt to different project scales and deployment environments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Monorepo Management Solution
&lt;/h2&gt;

&lt;p&gt;Since the project includes frontend, backend, UI component library, and utility packages, I opted for a Monorepo management solution. This approach enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralized management of all modules and unified dependency versions to avoid conflicts.&lt;/li&gt;
&lt;li&gt;Extracting shared modules (like ORM, UI components, TS configs, toolchains) into standalone packages for better modularity and focused business logic.&lt;/li&gt;
&lt;li&gt;Easier local development between packages without needing to publish them.&lt;/li&gt;
&lt;li&gt;Optimized CI/CD pipelines and improved build efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Finalized Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependency management: &lt;code&gt;pnpm workspace&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Build &amp;amp; task orchestration: &lt;code&gt;Turborepo&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;pnpm&lt;/code&gt; uses its workspace feature to manage dependencies easily across multiple packages in a Monorepo.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Turborepo&lt;/code&gt; is lightweight and flexible, perfectly complementing &lt;code&gt;pnpm&lt;/code&gt;'s Monorepo shortcomings. It focuses on configuration management, build processes, supports incremental builds, and caching. Backed by Vercel, it’s actively maintained and reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other Alternatives:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Lerna&lt;/code&gt;: An early Monorepo tool, which became unmaintained around 2020. It was later adopted by the Nx team (Nrwl) in 2022, but is no longer as active — not considered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Nx&lt;/code&gt;: A more powerful enterprise-grade Monorepo solution that doesn’t rely on &lt;code&gt;pnpm workspace&lt;/code&gt; for dependency management. It has stricter dependency control and recently introduced AI-first features. Highly promising but comes with a steeper learning curve — not adopting for now.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Backend Tech Choices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Finalized Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework: &lt;code&gt;NestJS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ORM: &lt;code&gt;Drizzle ORM&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;NestJS&lt;/code&gt; can use either Express or Fastify as its underlying HTTP framework. It defaults to Express and can seamlessly integrate third-party Express middleware, making it highly compatible within the ecosystem.&lt;br&gt;&lt;br&gt;
Think of NestJS as a Swiss Army knife built on Express, bundling many useful tools. Of course, one downside is you might not need all those built-in utilities, and you have to work within its dependency injection architecture.&lt;br&gt;&lt;br&gt;
That said, Express alone can get messy, and leveraging NestJS's integrated tools can greatly reduce decision-making and best practice research time. Architecturally, NestJS combines Object-Oriented Programming (OOP), Functional Programming (FP), and Reactive Programming (FRP) concepts — offering strong scalability and a clean project structure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Drizzle ORM&lt;/code&gt; is lightweight and strikes a good balance between TypeORM and Prisma. It’s popular for its Serverless compatibility and is one of the most trending ORMs currently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other Alternatives&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Express&lt;/code&gt;: The classic Node.js framework — highly flexible and mature. While building a custom Node.js web framework tailored to your tech stack is tempting, it demands too much time and energy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Next.js API Routes&lt;/code&gt;: Great for serverless backends tightly coupled with Next.js frontend, but that's a different development model. For this project, a more traditional backend is preferred for general-purpose use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TypeORM&lt;/code&gt;: A veteran ORM framework with high flexibility, but requires custom entity definitions, database access wrappers, transaction control, and migration management. Its configuration can be cumbersome and is better suited for projects needing highly customized SQL logic.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Prisma&lt;/code&gt;: The most popular TypeScript ORM today — excellent type safety, clean API, and an active community. Best for small to medium projects or cases with stable, rarely changing database schemas. That said, its raw SQL handling experience isn’t ideal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frontend Tech Choices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Finalized Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework: &lt;code&gt;React&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Styling: &lt;code&gt;Tailwind&lt;/code&gt; + &lt;code&gt;ShadCN/UI&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This frontend stack follows an AI-first development workflow, tailored for modern AI-assisted coding tools.&lt;br&gt;&lt;br&gt;
Notably, frameworks like V0.dev are built around the React ecosystem — practically making this combination a default stack.&lt;br&gt;&lt;br&gt;
Similarly, &lt;a href="https://docs.cline.bot/getting-started/our-favorite-tech-stack#recommended-stack-for-new-cline-users-2025" rel="noopener noreferrer"&gt;Cline&lt;/a&gt; also recommends this setup.&lt;/p&gt;

&lt;p&gt;For the admin system, a lightweight Vite + React-Router stack is used for fast builds and an excellent development experience — no SSR needed. In cases where SSR is required, Next.js remains the go-to option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;├── apps/
│   ├── admin/               # Frontend (React 19 + Vite)
│   └── api/                 # Backend service based on NestJS
├── packages/                # Shared packages
│   ├── db/                  # Drizzle ORM schemas &amp;amp; migration scripts
│   ├── ui/                  # UI component library based on ShadCN
│   ├── lint-config/         # Shared Eslint config
│   └── ts-config/           # Shared TypeScript config
├── .husky/                  
├── pnpm-workspace.yaml      # pnpm workspace configuration
├── turbo.json               # Turborepo build config
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Includes a simple admin system → see preview in the header image → or clone nestjs-boilerplate → run to preview.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
      <category>node</category>
    </item>
  </channel>
</rss>
