<?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: Salman Shahriar</title>
    <description>The latest articles on DEV Community by Salman Shahriar (@salmanshahriar).</description>
    <link>https://dev.to/salmanshahriar</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%2F1951722%2F6c136fda-088e-4813-ba06-de1af03134ea.jpeg</url>
      <title>DEV Community: Salman Shahriar</title>
      <link>https://dev.to/salmanshahriar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salmanshahriar"/>
    <language>en</language>
    <item>
      <title>Next.js SaaS Boilerplate with BetterAuth, RBAC, i18n &amp; Production-Ready Setup</title>
      <dc:creator>Salman Shahriar</dc:creator>
      <pubDate>Sat, 30 May 2026 20:13:57 +0000</pubDate>
      <link>https://dev.to/salmanshahriar/nextjs-saas-boilerplate-with-betterauth-rbac-i18n-production-ready-setup-bao</link>
      <guid>https://dev.to/salmanshahriar/nextjs-saas-boilerplate-with-betterauth-rbac-i18n-production-ready-setup-bao</guid>
      <description>&lt;p&gt;Every time I started a new Next.js project, I lost the first week to setup.&lt;/p&gt;

&lt;p&gt;Authentication. Internationalization. Role-based access. SEO meta tags. Environment validation. Error monitoring. Linting. Testing. CI pipelines.&lt;/p&gt;

&lt;p&gt;By the time I had a working foundation, the excitement was gone, buried under config files and boilerplate glue code.&lt;/p&gt;

&lt;p&gt;After doing this across multiple SaaS projects, I stopped and asked myself: &lt;em&gt;What if I built the foundation once, properly, and never had to do it again?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I did. Then I rebuilt it from scratch with a feature-sliced architecture and a clearer frontend-first scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result is &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Nextjs-Elite-Boilerplate&lt;/a&gt;&lt;/strong&gt; (v0.3.0): a production-ready, frontend-first Next.js 16 starter that's MIT-licensed and open source.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt; · 📦 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/strong&gt; · 🚀 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/generate" rel="noopener noreferrer"&gt;Use This Template&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Deploy on Vercel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&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%2Fzrxbcy0qwgkhadoewvnz.webp" 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%2Fzrxbcy0qwgkhadoewvnz.webp" alt="Next.js Elite — production-ready SaaS boilerplate cover" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fzmgm9ahn9q0db3y58bos.webp" 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%2Fzmgm9ahn9q0db3y58bos.webp" alt="Next.js Elite Boilerplate — Open Graph preview" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Another Boilerplate?&lt;/li&gt;
&lt;li&gt;What Makes This One Different&lt;/li&gt;
&lt;li&gt;Honest Caveats (So You Know What You're Getting)&lt;/li&gt;
&lt;li&gt;The Full Feature Breakdown&lt;/li&gt;
&lt;li&gt;Lighthouse? All 100s.&lt;/li&gt;
&lt;li&gt;Getting Started in 5 Minutes&lt;/li&gt;
&lt;li&gt;Production Checklist&lt;/li&gt;
&lt;li&gt;The Project Structure (For Humans)&lt;/li&gt;
&lt;li&gt;Everything You Get Out of the Box&lt;/li&gt;
&lt;li&gt;Who Should Use This (and Who Shouldn't)&lt;/li&gt;
&lt;li&gt;Contributing&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="why-another-boilerplate"&gt;Why Another Boilerplate?&lt;/h2&gt;

&lt;p&gt;I know what you're thinking. &lt;em&gt;The world doesn't need another Next.js starter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Honestly? Most of the time, you'd be right. Most starters fall into two camps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Too bare.&lt;/strong&gt; A &lt;code&gt;create-next-app&lt;/code&gt; with a theme toggle and a "TODO: add auth here" comment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Too opinionated.&lt;/strong&gt; Ships with a Prisma schema, a specific database, and an ORM you didn't ask for, tightly coupling you to decisions you haven't made yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted something in between: a &lt;strong&gt;frontend-first foundation&lt;/strong&gt; that handles auth, roles, i18n, SEO, forms, data fetching, error monitoring, and developer tooling, but doesn't force a database on you. You bring your own API (REST, GraphQL, BFF, whatever), and this boilerplate handles everything else.&lt;/p&gt;

&lt;p&gt;That's what Next.js Elite is. And it's free, MIT-licensed, and open source.&lt;/p&gt;




&lt;h2 id="what-makes-this-one-different"&gt;What Makes This One Different&lt;/h2&gt;

&lt;p&gt;Here's what you get with a single &lt;code&gt;git clone&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16 + React 19&lt;/strong&gt; with App Router and Server Components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BetterAuth&lt;/strong&gt; with email/password and optional Google OAuth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission-based RBAC&lt;/strong&gt; using parallel routes (&lt;code&gt;@admin&lt;/code&gt;, &lt;code&gt;@user&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safe i18n&lt;/strong&gt; via next-intl: 6 languages, RTL, cookie-based locale, compile-time checked keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;T3 Env&lt;/strong&gt; for Zod-validated environment variables (server + client split)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Query + ofetch&lt;/strong&gt; (&lt;code&gt;apiFetch&lt;/code&gt;) for API data fetching with Zod response parsing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Hook Form + Zod&lt;/strong&gt; for forms with shared validation schemas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentry&lt;/strong&gt; for error monitoring, &lt;strong&gt;pino&lt;/strong&gt; for server logging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional Upstash&lt;/strong&gt; helpers for rate limiting (when env vars are set)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vitest + Playwright&lt;/strong&gt; for unit and E2E testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lefthook + Commitlint + Knip&lt;/strong&gt; for automated code quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One JSON file&lt;/strong&gt; drives SEO, sitemap, robots.txt, and manifest config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo mode&lt;/strong&gt; for instant previews on the login page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker + Vercel&lt;/strong&gt; deployment ready (&lt;code&gt;output: 'standalone'&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the Lighthouse scores? Well...&lt;/p&gt;




&lt;h2 id="honest-caveats"&gt;Honest Caveats (So You Know What You're Getting)&lt;/h2&gt;

&lt;p&gt;The homepage hero cards describe what ships today. These six caveats match those cards and what the repo actually does — no overselling.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modern stack, lean setup&lt;/strong&gt; — API-driven by design: no ORM or database layer. The example &lt;code&gt;users&lt;/code&gt; client expects &lt;strong&gt;your&lt;/strong&gt; &lt;code&gt;/api/users&lt;/code&gt; or an external API; &lt;strong&gt;no mock DB&lt;/strong&gt; is included.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BetterAuth&lt;/strong&gt; — Auth works out of the box for local and demo use. For &lt;strong&gt;multi-instance production&lt;/strong&gt;, configure a &lt;strong&gt;Better Auth storage adapter&lt;/strong&gt; so sessions persist across instances (BetterAuth defaults are not shared across nodes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallel routing&lt;/strong&gt; — &lt;code&gt;@user&lt;/code&gt; / &lt;code&gt;@admin&lt;/code&gt; slots share &lt;code&gt;/dashboard&lt;/code&gt;, but permissions are &lt;strong&gt;starter-grade RBAC&lt;/strong&gt; (two roles, email allowlist for admin). Extend roles in your backend when you need multi-tenant or org-level access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type-safe i18n&lt;/strong&gt; — Locale lives in a &lt;strong&gt;cookie&lt;/strong&gt; (&lt;code&gt;NEXT_LOCALE&lt;/code&gt;; no &lt;code&gt;/en&lt;/code&gt; or &lt;code&gt;/fr&lt;/code&gt; URL prefixes): &lt;strong&gt;simpler UX&lt;/strong&gt;, not path-prefixed locales for multilingual SEO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEO + PWA, server-first&lt;/strong&gt; — Metadata, sitemap, robots, and JSON-LD come from &lt;code&gt;site.config.json&lt;/code&gt;. Replace placeholder org/domain values before you ship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer experience&lt;/strong&gt; — CI runs typecheck → lint → knip → test → build. Test coverage is &lt;strong&gt;starter-level&lt;/strong&gt; (RBAC/i18n unit tests + light E2E). Optional &lt;code&gt;getRateLimiter()&lt;/code&gt; exists in &lt;code&gt;src/libs/rate-limit.ts&lt;/code&gt; but is &lt;strong&gt;not wired&lt;/strong&gt; to auth or API routes by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="lighthouse-all-100s"&gt;Lighthouse? All 100s.&lt;/h2&gt;

&lt;p&gt;This isn't just "good enough for a starter." The boilerplate scores &lt;strong&gt;100 across all four Lighthouse categories&lt;/strong&gt;: Performance, Accessibility, Best Practices, and SEO, right out of the box.&lt;/p&gt;

&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%2Fqs3yt1sm6c7lyccym6rg.webp" 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%2Fqs3yt1sm6c7lyccym6rg.webp" alt="Lighthouse report showing perfect 100 scores in Performance, Accessibility, Best Practices, and SEO" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No tricks. No deferred audits. That's the production build, tested against the live demo at &lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;nextjs-elite-boilerplate.vercel.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most boilerplates treat performance as an afterthought. Here, it's baked in from day one: server components by default, client components only where needed, semantic HTML, proper heading hierarchy, and optimized asset loading.&lt;/p&gt;




&lt;h2 id="the-full-feature-breakdown"&gt;The Full Feature Breakdown&lt;/h2&gt;

&lt;p&gt;Let's walk through every major system. I'll cover &lt;em&gt;what&lt;/em&gt; it does, &lt;em&gt;why&lt;/em&gt; I chose it, and how it works in this codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication: BetterAuth
&lt;/h3&gt;

&lt;p&gt;Auth is built on &lt;strong&gt;&lt;a href="https://www.better-auth.com/" rel="noopener noreferrer"&gt;BetterAuth&lt;/a&gt;&lt;/strong&gt;, exposed at &lt;code&gt;/api/auth/*&lt;/code&gt; via &lt;code&gt;src/app/api/auth/[...all]/route.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's what you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email/password sign-up and login&lt;/strong&gt; — works immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google OAuth&lt;/strong&gt; — set &lt;code&gt;GOOGLE_CLIENT_ID&lt;/code&gt; / &lt;code&gt;GOOGLE_CLIENT_SECRET&lt;/code&gt; and &lt;code&gt;NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side session reads&lt;/strong&gt; — &lt;code&gt;getCurrentUser()&lt;/code&gt; in Server Components; client uses &lt;code&gt;authClient.useSession()&lt;/code&gt; via the auth provider&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin role mapping&lt;/strong&gt; — comma-separated emails in &lt;code&gt;AUTH_ADMIN_EMAILS&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_AUTH_ADMIN_EMAILS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sessions use &lt;strong&gt;BetterAuth's default storage&lt;/strong&gt;. For production on multiple instances, plug in a &lt;strong&gt;database or Redis adapter&lt;/strong&gt; — see the &lt;a href="https://www.better-auth.com/docs" rel="noopener noreferrer"&gt;BetterAuth docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo mode&lt;/strong&gt; lives in &lt;code&gt;src/features/auth/demo/&lt;/code&gt;. With &lt;code&gt;NEXT_PUBLIC_DEMO_MODE=true&lt;/code&gt;, the login page shows click-to-fill credentials and auto-registers seed accounts on first sign-in:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Email&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user@test.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12345678&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Admin&lt;/td&gt;
&lt;td&gt;&lt;code&gt;admin@test.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12345678&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Going to production? Set the flag to &lt;code&gt;false&lt;/code&gt;, or delete the &lt;code&gt;demo/&lt;/code&gt; folder. Nothing else imports it except the login flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC: Permissions, Not Just Roles
&lt;/h3&gt;

&lt;p&gt;Most boilerplates give you &lt;code&gt;if (role === 'admin')&lt;/code&gt; checks scattered across your code. That doesn't scale.&lt;/p&gt;

&lt;p&gt;Next.js Elite uses &lt;strong&gt;permission-based RBAC&lt;/strong&gt;. Each role maps to permissions; pages check permissions, not raw role strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;requirePermission&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/auth/rbac/require&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AdminDashboardPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;requirePermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard.view:admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;back&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invalid sessions redirect to &lt;code&gt;/login&lt;/code&gt;. Insufficient permissions redirect to &lt;code&gt;/unauthorized&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The routing layer uses &lt;strong&gt;Next.js parallel routes&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/app/(protected)/
  @admin/dashboard/    → Admin sees this
  @user/dashboard/     → Regular users see this
  layout.tsx           → Picks the right slot based on permissions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today there are two roles (&lt;code&gt;user&lt;/code&gt;, &lt;code&gt;admin&lt;/code&gt;) and two dashboard permissions. Admin is granted via &lt;strong&gt;email allowlist&lt;/strong&gt;, not a database role table — extend &lt;code&gt;rbac/roles.ts&lt;/code&gt; and your backend when you outgrow that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internationalization: next-intl with Type Safety
&lt;/h3&gt;

&lt;p&gt;The boilerplate uses &lt;strong&gt;&lt;a href="https://next-intl.dev/" rel="noopener noreferrer"&gt;next-intl&lt;/a&gt;&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cookie-based locale&lt;/strong&gt; (&lt;code&gt;NEXT_LOCALE&lt;/code&gt;) — no &lt;code&gt;/en/&lt;/code&gt; or &lt;code&gt;/fr/&lt;/code&gt; URL prefixes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 languages&lt;/strong&gt; out of the box: English, বাংলা, العربية (full RTL), Français, Español, 简体中文&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time type checking&lt;/strong&gt; — &lt;code&gt;t("navigation.home")&lt;/code&gt; autocompletes; typos fail the build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Translation files live in &lt;code&gt;messages/&lt;/code&gt;. Add a language in &lt;code&gt;site.config.json&lt;/code&gt;, create &lt;code&gt;messages/&amp;lt;locale&amp;gt;.json&lt;/code&gt;, and the runtime picks it up.&lt;/p&gt;

&lt;h3&gt;
  
  
  SEO: One Config File
&lt;/h3&gt;

&lt;p&gt;SEO is driven by &lt;code&gt;src/features/site/site.config.json&lt;/code&gt;, validated with Zod in &lt;code&gt;src/features/site/config.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That one file drives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Graph and Twitter Card meta tags&lt;/li&gt;
&lt;li&gt;JSON-LD structured data (&lt;code&gt;Organization&lt;/code&gt;, &lt;code&gt;WebSite&lt;/code&gt;, &lt;code&gt;SoftwareApplication&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Dynamic sitemap and robots.txt&lt;/li&gt;
&lt;li&gt;PWA web app manifest&lt;/li&gt;
&lt;li&gt;Canonical URLs and theme colors
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My SaaS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mysaas.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My SaaS — Do X Better"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"We help Y achieve Z."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"organization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Company"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mysaas.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"images"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"og"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/og-image.webp"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data Fetching: ofetch + TanStack Query
&lt;/h3&gt;

&lt;p&gt;The API layer uses &lt;strong&gt;&lt;a href="https://github.com/unjs/ofetch" rel="noopener noreferrer"&gt;ofetch&lt;/a&gt;&lt;/strong&gt; via &lt;code&gt;apiFetch&lt;/code&gt; in &lt;code&gt;src/libs/api-client.ts&lt;/code&gt; (defaults to same-origin &lt;code&gt;/api&lt;/code&gt;) and &lt;strong&gt;&lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt;&lt;/strong&gt; on the client.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;users&lt;/code&gt; feature is a copy-paste pattern — &lt;strong&gt;you&lt;/strong&gt; implement &lt;code&gt;/api/users&lt;/code&gt; or point &lt;code&gt;NEXT_PUBLIC_APP_URL&lt;/code&gt; at your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useUsers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/users/hooks/use-users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/features/users/api.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apiFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userListSchema&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Forms: React Hook Form + Zod
&lt;/h3&gt;

&lt;p&gt;Every auth form uses &lt;strong&gt;&lt;a href="https://react-hook-form.com/" rel="noopener noreferrer"&gt;React Hook Form&lt;/a&gt;&lt;/strong&gt; with Zod resolvers. Schemas live in &lt;code&gt;src/features/auth/schemas/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;zodResolver&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hookform/resolvers/zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-hook-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loginSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LoginInput&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/auth/schemas/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoginInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zodResolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginSchema&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;defaultValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment Variables: T3 Env
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://env.t3.gg/" rel="noopener noreferrer"&gt;@t3-oss/env-nextjs&lt;/a&gt;&lt;/strong&gt; + Zod validates server and client env vars at build time. &lt;code&gt;SKIP_ENV_VALIDATION=true&lt;/code&gt; is supported for CI and Docker builds. A missing &lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt; in production logs a warning at runtime (placeholder only for local dev).&lt;/p&gt;

&lt;h3&gt;
  
  
  UI: shadcn/ui + Tailwind CSS v4
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui&lt;/a&gt;&lt;/strong&gt; (Radix + CVA + Tailwind v4). Components live in &lt;code&gt;src/components/ui/&lt;/code&gt; — copy and own them.&lt;/p&gt;

&lt;p&gt;Dark mode uses a &lt;strong&gt;lightweight custom theme provider&lt;/strong&gt; in &lt;code&gt;src/features/theme/&lt;/code&gt; (system / light / dark) with a toggle in the header — no &lt;code&gt;next-themes&lt;/code&gt; dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability: Sentry + pino + Rate Limiting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;&lt;/strong&gt; — &lt;code&gt;src/instrumentation.ts&lt;/code&gt; (server) and &lt;code&gt;src/instrumentation-client.ts&lt;/code&gt; (client). Set &lt;code&gt;SENTRY_DSN&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_SENTRY_DSN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/pinojs/pino" rel="noopener noreferrer"&gt;pino&lt;/a&gt;&lt;/strong&gt; — structured server logging in &lt;code&gt;src/libs/logger.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/upstash/ratelimit" rel="noopener noreferrer"&gt;@upstash/ratelimit&lt;/a&gt;&lt;/strong&gt; — optional &lt;code&gt;getRateLimiter()&lt;/code&gt; / &lt;code&gt;isRateLimited()&lt;/code&gt; in &lt;code&gt;src/libs/rate-limit.ts&lt;/code&gt; when &lt;code&gt;UPSTASH_REDIS_*&lt;/code&gt; is set. Wire it into your route handlers where you need protection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing: Vitest + Playwright
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit tests&lt;/strong&gt;: Vitest + React Testing Library. Specs in &lt;code&gt;tests/&lt;/code&gt; (auth, i18n) and colocated &lt;code&gt;*.test.tsx&lt;/code&gt; under &lt;code&gt;src/components/ui/&lt;/code&gt; and &lt;code&gt;src/libs/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2E&lt;/strong&gt;: Playwright in &lt;code&gt;e2e/&lt;/code&gt; — home, health check, login page smoke tests. Run &lt;code&gt;npm run e2e&lt;/code&gt; (config: &lt;code&gt;e2e/playwright.config.ts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt;: &lt;code&gt;.github/workflows/check.yml&lt;/code&gt; (typecheck → lint → knip → test → build) and &lt;code&gt;playwright.yml&lt;/code&gt; for E2E.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Developer Experience: The Full Pipeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/evilmartians/lefthook" rel="noopener noreferrer"&gt;Lefthook&lt;/a&gt;&lt;/strong&gt; — pre-commit lint/format, commit-msg Commitlint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://knip.dev/" rel="noopener noreferrer"&gt;Knip&lt;/a&gt;&lt;/strong&gt; — unused files, exports, and dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.renovatebot.com/" rel="noopener noreferrer"&gt;Renovate&lt;/a&gt;&lt;/strong&gt; — automated dependency updates (&lt;code&gt;.github/renovate.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint 9 flat config&lt;/strong&gt; + Prettier (Tailwind class sorting)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel Analytics&lt;/strong&gt; — included in the root layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;proxy.ts&lt;/code&gt; is a pass-through middleware placeholder — auth and locale are handled in Server Components and &lt;code&gt;next-intl&lt;/code&gt; request config, not at the edge.&lt;/p&gt;




&lt;h2 id="getting-started-in-5-minutes"&gt;Getting Started in 5 Minutes&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Node.js 20.9+, npm / pnpm / yarn / bun.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clone and install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Nextjs-Elite-Boilerplate
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set up environment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key variables (see &lt;code&gt;.env.example&lt;/code&gt; for the full list):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt; — 32+ chars in production (&lt;code&gt;openssl rand -base64 32&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BETTER_AUTH_URL&lt;/code&gt; — optional; auto-derived on Vercel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true&lt;/code&gt; + Google credentials for OAuth&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NEXT_PUBLIC_DEMO_MODE=true&lt;/code&gt; for instant test accounts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SKIP_ENV_VALIDATION=true&lt;/code&gt; for CI/Docker when secrets aren't available yet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Brand it
&lt;/h3&gt;

&lt;p&gt;Edit &lt;code&gt;src/features/site/site.config.json&lt;/code&gt; — app name, domain, SEO, social links, locales.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add languages (optional)
&lt;/h3&gt;

&lt;p&gt;Add the locale to &lt;code&gt;site.config.json&lt;/code&gt;, create &lt;code&gt;messages/&amp;lt;locale&amp;gt;.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  All available scripts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dev server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Production build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Production server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run analyze&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bundle analysis (&lt;code&gt;ANALYZE=true&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run typecheck&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tsc --noEmit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESLint + Prettier check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint:fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-fix lint + format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run knip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dead code / dependency detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;typecheck + lint + knip + test (CI gate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vitest run (&lt;code&gt;config/vitest.config.ts&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run test:watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vitest watch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Playwright E2E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e:ui&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Playwright UI mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e:webkit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WebKit-only E2E&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vercel (one click):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvercel.com%2Fbutton" alt="Deploy with Vercel" width="103" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; nextjs-elite &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 nextjs-elite
&lt;span class="c"&gt;# or: docker compose up --build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2 id="production-checklist"&gt;Production Checklist&lt;/h2&gt;

&lt;p&gt;Before you ship:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a strong &lt;strong&gt;&lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt;&lt;/strong&gt; (32+ characters).&lt;/li&gt;
&lt;li&gt;Configure a &lt;strong&gt;Better Auth storage adapter&lt;/strong&gt; for multi-instance deploys.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;&lt;code&gt;NEXT_PUBLIC_DEMO_MODE=false&lt;/code&gt;&lt;/strong&gt; or remove &lt;code&gt;src/features/auth/demo/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;&lt;code&gt;/api/users&lt;/code&gt;&lt;/strong&gt; (or your real API) for features that call &lt;code&gt;apiFetch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Update &lt;strong&gt;&lt;code&gt;site.config.json&lt;/code&gt;&lt;/strong&gt; — real domain, org, and OG image (not placeholders).&lt;/li&gt;
&lt;li&gt;Optionally enable &lt;strong&gt;Sentry&lt;/strong&gt; and &lt;strong&gt;Upstash&lt;/strong&gt; rate limiting on sensitive routes.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="project-structure"&gt;The Project Structure (For Humans)&lt;/h2&gt;

&lt;p&gt;Feature-sliced architecture: each feature owns its components, hooks, schemas, and server logic. Cross-cutting infra lives in &lt;code&gt;libs/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── .github/workflows/        check.yml + playwright.yml
├── config/                   vitest.config.ts, vitest.setup.ts
├── e2e/                      Playwright specs + playwright.config.ts
├── messages/                 Translation files (en, bn, ar, fr, es, zh)
├── tests/                    Vitest specs (auth, i18n)
├── proxy.ts                  Middleware (pass-through)
├── lefthook.yml              Git hooks
├── knip.json                 Dead-code config
├── src/
│   ├── app/                  App Router
│   │   ├── (auth)/           Login, register, password reset
│   │   ├── (public)/         Marketing pages
│   │   ├── (protected)/      Auth-gated area
│   │   │   ├── @admin/       Admin dashboard slot
│   │   │   ├── @user/        User dashboard slot
│   │   │   └── layout.tsx    Permission-based slot picker
│   │   ├── api/              BetterAuth + health
│   │   ├── layout.tsx        Root layout + SEO
│   │   └── providers.tsx     Theme + Auth + Query
│   ├── components/
│   │   ├── shared/           Hero, logo, home sections
│   │   └── ui/               shadcn/ui primitives
│   ├── features/
│   │   ├── auth/             BetterAuth, RBAC, demo mode
│   │   ├── i18n/             next-intl config
│   │   ├── navigation/       Header + Sidebar
│   │   ├── site/             site.config.json + Zod parser
│   │   ├── theme/            Custom theme provider
│   │   └── users/            Example API + hooks
│   └── libs/                 env, api-client, logger, rate-limit, utils
└── package.json              scripts; Prettier + Commitlint config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key conventions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;features/&amp;lt;name&amp;gt;/&lt;/code&gt; — vertical slices&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;libs/&lt;/code&gt; — cross-cutting infra, no business logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;components/ui/&lt;/code&gt; — shadcn primitives; extend, don't fight the CLI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;schemas/&lt;/code&gt; — shared Zod schemas (e.g. API responses)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="out-of-the-box"&gt;Everything You Get Out of the Box&lt;/h2&gt;

&lt;p&gt;✅ Next.js 16 + React 19 (App Router, Server Components)&lt;br&gt;
✅ TypeScript 5.9 (strict)&lt;br&gt;
✅ Tailwind CSS v4&lt;br&gt;
✅ BetterAuth (email/password + optional Google OAuth)&lt;br&gt;
✅ Permission-based RBAC with parallel routes&lt;br&gt;
✅ next-intl (6 languages, RTL, type-safe, cookie-based)&lt;br&gt;
✅ T3 Env (Zod-validated server + client env vars)&lt;br&gt;
✅ TanStack Query + ofetch (&lt;code&gt;apiFetch&lt;/code&gt; + Zod parsing)&lt;br&gt;
✅ React Hook Form + Zod (auth forms + shared schemas)&lt;br&gt;
✅ SEO suite (OG, Twitter Cards, JSON-LD, sitemap, robots, manifest)&lt;br&gt;
✅ Custom theme provider (light / dark / system)&lt;br&gt;
✅ shadcn/ui (Radix + CVA + Tailwind)&lt;br&gt;
✅ Sentry (server + client instrumentation)&lt;br&gt;
✅ pino (structured server logging)&lt;br&gt;
✅ Optional Upstash rate limiting helpers&lt;br&gt;
✅ Vitest + React Testing Library&lt;br&gt;
✅ Playwright E2E&lt;br&gt;
✅ Lefthook + Commitlint&lt;br&gt;
✅ Knip (dead-code hygiene)&lt;br&gt;
✅ ESLint + Prettier&lt;br&gt;
✅ GitHub Actions CI + Playwright workflow&lt;br&gt;
✅ Docker + Docker Compose (&lt;code&gt;standalone&lt;/code&gt; output)&lt;br&gt;
✅ Demo mode (isolated &lt;code&gt;src/features/auth/demo/&lt;/code&gt;)&lt;br&gt;
✅ Health check (&lt;code&gt;GET /api/health&lt;/code&gt;)&lt;br&gt;
✅ Renovate + Vercel Analytics&lt;br&gt;
✅ Vercel one-click deploy&lt;/p&gt;




&lt;h2 id="who-should-use-this"&gt;Who Should Use This (and Who Shouldn't)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This is a good fit if you're building:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A SaaS product with multiple user roles&lt;/li&gt;
&lt;li&gt;An internationalized app (especially with RTL requirements)&lt;/li&gt;
&lt;li&gt;A frontend that consumes an existing API or BFF&lt;/li&gt;
&lt;li&gt;A project where you want auth, RBAC, i18n, and DX tooling on day one without inheriting a database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Probably not the right choice for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single-page landing site (more than you need)&lt;/li&gt;
&lt;li&gt;An app that needs a tightly-coupled database layer in the same repo (this is intentionally API-only)&lt;/li&gt;
&lt;li&gt;Enterprise RBAC with orgs, teams, and dynamic roles in the DB (start here, extend in your backend)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="contributing"&gt;Contributing&lt;/h2&gt;

&lt;p&gt;The project is fully open source and contributions are welcome:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork and branch from &lt;code&gt;main&lt;/code&gt; (&lt;code&gt;feat/...&lt;/code&gt;, &lt;code&gt;fix/...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm run check&lt;/code&gt; — it must pass&lt;/li&gt;
&lt;li&gt;Use Conventional Commits (Lefthook enforces this)&lt;/li&gt;
&lt;li&gt;Open a PR with a clear description&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🐛 &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/issues" rel="noopener noreferrer"&gt;Report a bug&lt;/a&gt; · ⭐ &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Star on GitHub&lt;/a&gt; · 🤝 &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/pulls" rel="noopener noreferrer"&gt;Submit a PR&lt;/a&gt;&lt;/p&gt;




&lt;h2 id="final-thoughts"&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I built the first version because I was tired of repeating myself. Then I rebuilt it with feature-sliced folders, BetterAuth, type-safe env and i18n, parallel-route dashboards, and a DX pipeline (Lefthook, Knip, Vitest, Playwright) that matches what I actually run before every push.&lt;/p&gt;

&lt;p&gt;The goal was never the &lt;em&gt;biggest&lt;/em&gt; starter kit. It was the one I want on &lt;strong&gt;day one&lt;/strong&gt; of a SaaS frontend — and still trust on &lt;strong&gt;day one hundred&lt;/strong&gt;, with a backend I chose myself.&lt;/p&gt;

&lt;p&gt;If it saves you a week of glue code, it was worth open-sourcing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your biggest pain point when starting a new Next.js project?&lt;/strong&gt; Drop a comment — I'm always looking for improvements that stay frontend-first.&lt;/p&gt;

&lt;p&gt;Happy building. 🚀&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt; · 📦 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; · 🚀 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/generate" rel="noopener noreferrer"&gt;Use Template&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Deploy on Vercel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>boilerplate</category>
      <category>saas</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a production ready NEXT.JS Boilerplate so you dont have to!</title>
      <dc:creator>Salman Shahriar</dc:creator>
      <pubDate>Wed, 19 Nov 2025 19:11:28 +0000</pubDate>
      <link>https://dev.to/salmanshahriar/i-built-a-production-ready-nextjs-boilerplate-so-you-dont-have-to-17d3</link>
      <guid>https://dev.to/salmanshahriar/i-built-a-production-ready-nextjs-boilerplate-so-you-dont-have-to-17d3</guid>
      <description>&lt;p&gt;Every time I started a new Next.js project, I lost the first week to setup.&lt;/p&gt;

&lt;p&gt;Authentication. Internationalization. Role-based access. SEO meta tags. Environment validation. Error monitoring. Linting. Testing. CI pipelines.&lt;/p&gt;

&lt;p&gt;By the time I had a working foundation, the excitement was gone, buried under config files and boilerplate glue code.&lt;/p&gt;

&lt;p&gt;After doing this across multiple SaaS projects, I stopped and asked myself: &lt;em&gt;What if I built the foundation once, properly, and never had to do it again?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I did. Then I rebuilt it from scratch with a feature-sliced architecture and a clearer frontend-first scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result is &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Nextjs-Elite-Boilerplate&lt;/a&gt;&lt;/strong&gt;: a production-ready, frontend-first Next.js 16 starter that's MIT-licensed and open source.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt; · 📦 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/strong&gt; · 🚀 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/generate" rel="noopener noreferrer"&gt;Use This Template&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Deploy on Vercel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&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%2Fl0pr8ej1pg3b444m7tcn.webp" 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%2Fl0pr8ej1pg3b444m7tcn.webp" alt="Next.js Elite — production-ready SaaS boilerplate cover" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fkviutx02fiz4tdgpj7kf.webp" 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%2Fkviutx02fiz4tdgpj7kf.webp" alt="Next.js Elite Boilerplate — Open Graph preview" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Another Boilerplate?&lt;/li&gt;
&lt;li&gt;What Makes This One Different&lt;/li&gt;
&lt;li&gt;Honest Caveats (So You Know What You're Getting)&lt;/li&gt;
&lt;li&gt;The Full Feature Breakdown&lt;/li&gt;
&lt;li&gt;Lighthouse? All 100s.&lt;/li&gt;
&lt;li&gt;Getting Started in 5 Minutes&lt;/li&gt;
&lt;li&gt;Production Checklist&lt;/li&gt;
&lt;li&gt;The Project Structure (For Humans)&lt;/li&gt;
&lt;li&gt;Everything You Get Out of the Box&lt;/li&gt;
&lt;li&gt;Who Should Use This (and Who Shouldn't)&lt;/li&gt;
&lt;li&gt;Contributing&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="why-another-boilerplate"&gt;Why Another Boilerplate?&lt;/h2&gt;

&lt;p&gt;I know what you're thinking. &lt;em&gt;The world doesn't need another Next.js starter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Honestly? Most of the time, you'd be right. Most starters fall into two camps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Too bare.&lt;/strong&gt; A &lt;code&gt;create-next-app&lt;/code&gt; with a theme toggle and a "TODO: add auth here" comment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Too opinionated.&lt;/strong&gt; Ships with a Prisma schema, a specific database, and an ORM you didn't ask for, tightly coupling you to decisions you haven't made yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted something in between: a &lt;strong&gt;frontend-first foundation&lt;/strong&gt; that handles auth, roles, i18n, SEO, forms, data fetching, error monitoring, and developer tooling, but doesn't force a database on you. You bring your own API (REST, GraphQL, BFF, whatever), and this boilerplate handles everything else.&lt;/p&gt;

&lt;p&gt;That's what Next.js Elite is. And it's free, MIT-licensed, and open source.&lt;/p&gt;




&lt;h2 id="what-makes-this-one-different"&gt;What Makes This One Different&lt;/h2&gt;

&lt;p&gt;Here's what you get with a single &lt;code&gt;git clone&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16 + React 19&lt;/strong&gt; with App Router and Server Components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BetterAuth&lt;/strong&gt; with email/password and optional Google OAuth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission-based RBAC&lt;/strong&gt; using parallel routes (&lt;code&gt;@admin&lt;/code&gt;, &lt;code&gt;@user&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safe i18n&lt;/strong&gt; via next-intl: 6 languages, RTL, cookie-based locale, compile-time checked keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;T3 Env&lt;/strong&gt; for Zod-validated environment variables (server + client split)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Query + ofetch&lt;/strong&gt; (&lt;code&gt;apiFetch&lt;/code&gt;) for API data fetching with Zod response parsing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Hook Form + Zod&lt;/strong&gt; for forms with shared validation schemas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentry&lt;/strong&gt; for error monitoring, &lt;strong&gt;pino&lt;/strong&gt; for server logging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional Upstash&lt;/strong&gt; helpers for rate limiting (when env vars are set)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vitest + Playwright&lt;/strong&gt; for unit and E2E testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lefthook + Commitlint + Knip&lt;/strong&gt; for automated code quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One JSON file&lt;/strong&gt; drives SEO, sitemap, robots.txt, and manifest config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo mode&lt;/strong&gt; for instant previews on the login page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker + Vercel&lt;/strong&gt; deployment ready (&lt;code&gt;output: 'standalone'&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the Lighthouse scores? Well...&lt;/p&gt;




&lt;h2 id="honest-caveats"&gt;Honest Caveats (So You Know What You're Getting)&lt;/h2&gt;

&lt;p&gt;The homepage hero cards describe what ships today. These six caveats match those cards and what the repo actually does — no overselling.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modern stack, lean setup&lt;/strong&gt; — API-driven by design: no ORM or database layer. The example &lt;code&gt;users&lt;/code&gt; client expects &lt;strong&gt;your&lt;/strong&gt; &lt;code&gt;/api/users&lt;/code&gt; or an external API; &lt;strong&gt;no mock DB&lt;/strong&gt; is included.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BetterAuth&lt;/strong&gt; — Auth works out of the box for local and demo use. For &lt;strong&gt;multi-instance production&lt;/strong&gt;, configure a &lt;strong&gt;Better Auth storage adapter&lt;/strong&gt; so sessions persist across instances (BetterAuth defaults are not shared across nodes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallel routing&lt;/strong&gt; — &lt;code&gt;@user&lt;/code&gt; / &lt;code&gt;@admin&lt;/code&gt; slots share &lt;code&gt;/dashboard&lt;/code&gt;, but permissions are &lt;strong&gt;starter-grade RBAC&lt;/strong&gt; (two roles, email allowlist for admin). Extend roles in your backend when you need multi-tenant or org-level access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type-safe i18n&lt;/strong&gt; — Locale lives in a &lt;strong&gt;cookie&lt;/strong&gt; (&lt;code&gt;NEXT_LOCALE&lt;/code&gt;; no &lt;code&gt;/en&lt;/code&gt; or &lt;code&gt;/fr&lt;/code&gt; URL prefixes): &lt;strong&gt;simpler UX&lt;/strong&gt;, not path-prefixed locales for multilingual SEO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEO + PWA, server-first&lt;/strong&gt; — Metadata, sitemap, robots, and JSON-LD come from &lt;code&gt;site.config.json&lt;/code&gt;. Replace placeholder org/domain values before you ship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer experience&lt;/strong&gt; — CI runs typecheck → lint → knip → test → build. Test coverage is &lt;strong&gt;starter-level&lt;/strong&gt; (RBAC/i18n unit tests + light E2E). Optional &lt;code&gt;getRateLimiter()&lt;/code&gt; exists in &lt;code&gt;src/libs/rate-limit.ts&lt;/code&gt; but is &lt;strong&gt;not wired&lt;/strong&gt; to auth or API routes by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="lighthouse-all-100s"&gt;Lighthouse? All 100s.&lt;/h2&gt;

&lt;p&gt;This isn't just "good enough for a starter." The boilerplate scores &lt;strong&gt;100 across all four Lighthouse categories&lt;/strong&gt;: Performance, Accessibility, Best Practices, and SEO, right out of the box.&lt;/p&gt;

&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%2Fqs3yt1sm6c7lyccym6rg.webp" 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%2Fqs3yt1sm6c7lyccym6rg.webp" alt="Lighthouse report showing perfect 100 scores in Performance, Accessibility, Best Practices, and SEO" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No tricks. No deferred audits. That's the production build, tested against the live demo at &lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;nextjs-elite-boilerplate.vercel.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most boilerplates treat performance as an afterthought. Here, it's baked in from day one: server components by default, client components only where needed, semantic HTML, proper heading hierarchy, and optimized asset loading.&lt;/p&gt;




&lt;h2 id="the-full-feature-breakdown"&gt;The Full Feature Breakdown&lt;/h2&gt;

&lt;p&gt;Let's walk through every major system. I'll cover &lt;em&gt;what&lt;/em&gt; it does, &lt;em&gt;why&lt;/em&gt; I chose it, and how it works in this codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication: BetterAuth
&lt;/h3&gt;

&lt;p&gt;Auth is built on &lt;strong&gt;&lt;a href="https://www.better-auth.com/" rel="noopener noreferrer"&gt;BetterAuth&lt;/a&gt;&lt;/strong&gt;, exposed at &lt;code&gt;/api/auth/*&lt;/code&gt; via &lt;code&gt;src/app/api/auth/[...all]/route.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's what you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email/password sign-up and login&lt;/strong&gt; — works immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google OAuth&lt;/strong&gt; — set &lt;code&gt;GOOGLE_CLIENT_ID&lt;/code&gt; / &lt;code&gt;GOOGLE_CLIENT_SECRET&lt;/code&gt; and &lt;code&gt;NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side session reads&lt;/strong&gt; — &lt;code&gt;getCurrentUser()&lt;/code&gt; in Server Components; client uses &lt;code&gt;authClient.useSession()&lt;/code&gt; via the auth provider&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin role mapping&lt;/strong&gt; — comma-separated emails in &lt;code&gt;AUTH_ADMIN_EMAILS&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_AUTH_ADMIN_EMAILS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sessions use &lt;strong&gt;BetterAuth's default storage&lt;/strong&gt;. For production on multiple instances, plug in a &lt;strong&gt;database or Redis adapter&lt;/strong&gt; — see the &lt;a href="https://www.better-auth.com/docs" rel="noopener noreferrer"&gt;BetterAuth docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo mode&lt;/strong&gt; lives in &lt;code&gt;src/features/auth/demo/&lt;/code&gt;. With &lt;code&gt;NEXT_PUBLIC_DEMO_MODE=true&lt;/code&gt;, the login page shows click-to-fill credentials and auto-registers seed accounts on first sign-in:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Email&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user@test.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12345678&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Admin&lt;/td&gt;
&lt;td&gt;&lt;code&gt;admin@test.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12345678&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Going to production? Set the flag to &lt;code&gt;false&lt;/code&gt;, or delete the &lt;code&gt;demo/&lt;/code&gt; folder. Nothing else imports it except the login flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC: Permissions, Not Just Roles
&lt;/h3&gt;

&lt;p&gt;Most boilerplates give you &lt;code&gt;if (role === 'admin')&lt;/code&gt; checks scattered across your code. That doesn't scale.&lt;/p&gt;

&lt;p&gt;Next.js Elite uses &lt;strong&gt;permission-based RBAC&lt;/strong&gt;. Each role maps to permissions; pages check permissions, not raw role strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;requirePermission&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/auth/rbac/require&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AdminDashboardPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;requirePermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard.view:admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;back&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invalid sessions redirect to &lt;code&gt;/login&lt;/code&gt;. Insufficient permissions redirect to &lt;code&gt;/unauthorized&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The routing layer uses &lt;strong&gt;Next.js parallel routes&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/app/(protected)/
  @admin/dashboard/    → Admin sees this
  @user/dashboard/     → Regular users see this
  layout.tsx           → Picks the right slot based on permissions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today there are two roles (&lt;code&gt;user&lt;/code&gt;, &lt;code&gt;admin&lt;/code&gt;) and two dashboard permissions. Admin is granted via &lt;strong&gt;email allowlist&lt;/strong&gt;, not a database role table — extend &lt;code&gt;rbac/roles.ts&lt;/code&gt; and your backend when you outgrow that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internationalization: next-intl with Type Safety
&lt;/h3&gt;

&lt;p&gt;The boilerplate uses &lt;strong&gt;&lt;a href="https://next-intl.dev/" rel="noopener noreferrer"&gt;next-intl&lt;/a&gt;&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cookie-based locale&lt;/strong&gt; (&lt;code&gt;NEXT_LOCALE&lt;/code&gt;) — no &lt;code&gt;/en/&lt;/code&gt; or &lt;code&gt;/fr/&lt;/code&gt; URL prefixes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 languages&lt;/strong&gt; out of the box: English, বাংলা, العربية (full RTL), Français, Español, 简体中文&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time type checking&lt;/strong&gt; — &lt;code&gt;t("navigation.home")&lt;/code&gt; autocompletes; typos fail the build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Translation files live in &lt;code&gt;messages/&lt;/code&gt;. Add a language in &lt;code&gt;site.config.json&lt;/code&gt;, create &lt;code&gt;messages/&amp;lt;locale&amp;gt;.json&lt;/code&gt;, and the runtime picks it up.&lt;/p&gt;

&lt;h3&gt;
  
  
  SEO: One Config File
&lt;/h3&gt;

&lt;p&gt;SEO is driven by &lt;code&gt;src/features/site/site.config.json&lt;/code&gt;, validated with Zod in &lt;code&gt;src/features/site/config.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That one file drives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Graph and Twitter Card meta tags&lt;/li&gt;
&lt;li&gt;JSON-LD structured data (&lt;code&gt;Organization&lt;/code&gt;, &lt;code&gt;WebSite&lt;/code&gt;, &lt;code&gt;SoftwareApplication&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Dynamic sitemap and robots.txt&lt;/li&gt;
&lt;li&gt;PWA web app manifest&lt;/li&gt;
&lt;li&gt;Canonical URLs and theme colors
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My SaaS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mysaas.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My SaaS — Do X Better"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"We help Y achieve Z."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"organization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Company"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mysaas.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"images"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"og"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/og-image.webp"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data Fetching: ofetch + TanStack Query
&lt;/h3&gt;

&lt;p&gt;The API layer uses &lt;strong&gt;&lt;a href="https://github.com/unjs/ofetch" rel="noopener noreferrer"&gt;ofetch&lt;/a&gt;&lt;/strong&gt; via &lt;code&gt;apiFetch&lt;/code&gt; in &lt;code&gt;src/libs/api-client.ts&lt;/code&gt; (defaults to same-origin &lt;code&gt;/api&lt;/code&gt;) and &lt;strong&gt;&lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt;&lt;/strong&gt; on the client.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;users&lt;/code&gt; feature is a copy-paste pattern — &lt;strong&gt;you&lt;/strong&gt; implement &lt;code&gt;/api/users&lt;/code&gt; or point &lt;code&gt;NEXT_PUBLIC_APP_URL&lt;/code&gt; at your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useUsers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/users/hooks/use-users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/features/users/api.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apiFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userListSchema&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Forms: React Hook Form + Zod
&lt;/h3&gt;

&lt;p&gt;Every auth form uses &lt;strong&gt;&lt;a href="https://react-hook-form.com/" rel="noopener noreferrer"&gt;React Hook Form&lt;/a&gt;&lt;/strong&gt; with Zod resolvers. Schemas live in &lt;code&gt;src/features/auth/schemas/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;zodResolver&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hookform/resolvers/zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-hook-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loginSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LoginInput&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/features/auth/schemas/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoginInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zodResolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginSchema&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;defaultValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment Variables: T3 Env
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://env.t3.gg/" rel="noopener noreferrer"&gt;@t3-oss/env-nextjs&lt;/a&gt;&lt;/strong&gt; + Zod validates server and client env vars at build time. &lt;code&gt;SKIP_ENV_VALIDATION=true&lt;/code&gt; is supported for CI and Docker builds. A missing &lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt; in production logs a warning at runtime (placeholder only for local dev).&lt;/p&gt;

&lt;h3&gt;
  
  
  UI: shadcn/ui + Tailwind CSS v4
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui&lt;/a&gt;&lt;/strong&gt; (Radix + CVA + Tailwind v4). Components live in &lt;code&gt;src/components/ui/&lt;/code&gt; — copy and own them.&lt;/p&gt;

&lt;p&gt;Dark mode uses a &lt;strong&gt;lightweight custom theme provider&lt;/strong&gt; in &lt;code&gt;src/features/theme/&lt;/code&gt; (system / light / dark) with a toggle in the header — no &lt;code&gt;next-themes&lt;/code&gt; dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability: Sentry + pino + Rate Limiting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;&lt;/strong&gt; — &lt;code&gt;src/instrumentation.ts&lt;/code&gt; (server) and &lt;code&gt;src/instrumentation-client.ts&lt;/code&gt; (client). Set &lt;code&gt;SENTRY_DSN&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_SENTRY_DSN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/pinojs/pino" rel="noopener noreferrer"&gt;pino&lt;/a&gt;&lt;/strong&gt; — structured server logging in &lt;code&gt;src/libs/logger.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/upstash/ratelimit" rel="noopener noreferrer"&gt;@upstash/ratelimit&lt;/a&gt;&lt;/strong&gt; — optional &lt;code&gt;getRateLimiter()&lt;/code&gt; / &lt;code&gt;isRateLimited()&lt;/code&gt; in &lt;code&gt;src/libs/rate-limit.ts&lt;/code&gt; when &lt;code&gt;UPSTASH_REDIS_*&lt;/code&gt; is set. Wire it into your route handlers where you need protection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing: Vitest + Playwright
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit tests&lt;/strong&gt;: Vitest + React Testing Library. Specs in &lt;code&gt;tests/&lt;/code&gt; (auth, i18n) and colocated &lt;code&gt;*.test.tsx&lt;/code&gt; under &lt;code&gt;src/components/ui/&lt;/code&gt; and &lt;code&gt;src/libs/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2E&lt;/strong&gt;: Playwright in &lt;code&gt;e2e/&lt;/code&gt; — home, health check, login page smoke tests. Run &lt;code&gt;npm run e2e&lt;/code&gt; (config: &lt;code&gt;e2e/playwright.config.ts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt;: &lt;code&gt;.github/workflows/check.yml&lt;/code&gt; (typecheck → lint → knip → test → build) and &lt;code&gt;playwright.yml&lt;/code&gt; for E2E.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Developer Experience: The Full Pipeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/evilmartians/lefthook" rel="noopener noreferrer"&gt;Lefthook&lt;/a&gt;&lt;/strong&gt; — pre-commit lint/format, commit-msg Commitlint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://knip.dev/" rel="noopener noreferrer"&gt;Knip&lt;/a&gt;&lt;/strong&gt; — unused files, exports, and dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.renovatebot.com/" rel="noopener noreferrer"&gt;Renovate&lt;/a&gt;&lt;/strong&gt; — automated dependency updates (&lt;code&gt;.github/renovate.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint 9 flat config&lt;/strong&gt; + Prettier (Tailwind class sorting)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel Analytics&lt;/strong&gt; — included in the root layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;proxy.ts&lt;/code&gt; is a pass-through middleware placeholder — auth and locale are handled in Server Components and &lt;code&gt;next-intl&lt;/code&gt; request config, not at the edge.&lt;/p&gt;




&lt;h2 id="getting-started-in-5-minutes"&gt;Getting Started in 5 Minutes&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Node.js 20.9+, npm / pnpm / yarn / bun.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clone and install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Nextjs-Elite-Boilerplate
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set up environment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key variables (see &lt;code&gt;.env.example&lt;/code&gt; for the full list):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt; — 32+ chars in production (&lt;code&gt;openssl rand -base64 32&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BETTER_AUTH_URL&lt;/code&gt; — optional; auto-derived on Vercel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true&lt;/code&gt; + Google credentials for OAuth&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NEXT_PUBLIC_DEMO_MODE=true&lt;/code&gt; for instant test accounts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SKIP_ENV_VALIDATION=true&lt;/code&gt; for CI/Docker when secrets aren't available yet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Brand it
&lt;/h3&gt;

&lt;p&gt;Edit &lt;code&gt;src/features/site/site.config.json&lt;/code&gt; — app name, domain, SEO, social links, locales.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add languages (optional)
&lt;/h3&gt;

&lt;p&gt;Add the locale to &lt;code&gt;site.config.json&lt;/code&gt;, create &lt;code&gt;messages/&amp;lt;locale&amp;gt;.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  All available scripts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dev server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Production build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Production server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run analyze&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bundle analysis (&lt;code&gt;ANALYZE=true&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run typecheck&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tsc --noEmit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESLint + Prettier check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint:fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-fix lint + format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run knip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dead code / dependency detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;typecheck + lint + knip + test (CI gate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vitest run (&lt;code&gt;config/vitest.config.ts&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run test:watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vitest watch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Playwright E2E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e:ui&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Playwright UI mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run e2e:webkit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WebKit-only E2E&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vercel (one click):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvercel.com%2Fbutton" alt="Deploy with Vercel" width="103" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; nextjs-elite &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 nextjs-elite
&lt;span class="c"&gt;# or: docker compose up --build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2 id="production-checklist"&gt;Production Checklist&lt;/h2&gt;

&lt;p&gt;Before you ship:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a strong &lt;strong&gt;&lt;code&gt;BETTER_AUTH_SECRET&lt;/code&gt;&lt;/strong&gt; (32+ characters).&lt;/li&gt;
&lt;li&gt;Configure a &lt;strong&gt;Better Auth storage adapter&lt;/strong&gt; for multi-instance deploys.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;&lt;code&gt;NEXT_PUBLIC_DEMO_MODE=false&lt;/code&gt;&lt;/strong&gt; or remove &lt;code&gt;src/features/auth/demo/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;&lt;code&gt;/api/users&lt;/code&gt;&lt;/strong&gt; (or your real API) for features that call &lt;code&gt;apiFetch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Update &lt;strong&gt;&lt;code&gt;site.config.json&lt;/code&gt;&lt;/strong&gt; — real domain, org, and OG image (not placeholders).&lt;/li&gt;
&lt;li&gt;Optionally enable &lt;strong&gt;Sentry&lt;/strong&gt; and &lt;strong&gt;Upstash&lt;/strong&gt; rate limiting on sensitive routes.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2 id="project-structure"&gt;The Project Structure (For Humans)&lt;/h2&gt;

&lt;p&gt;Feature-sliced architecture: each feature owns its components, hooks, schemas, and server logic. Cross-cutting infra lives in &lt;code&gt;libs/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── .github/workflows/        check.yml + playwright.yml
├── config/                   vitest.config.ts, vitest.setup.ts
├── e2e/                      Playwright specs + playwright.config.ts
├── messages/                 Translation files (en, bn, ar, fr, es, zh)
├── tests/                    Vitest specs (auth, i18n)
├── proxy.ts                  Middleware (pass-through)
├── lefthook.yml              Git hooks
├── knip.json                 Dead-code config
├── src/
│   ├── app/                  App Router
│   │   ├── (auth)/           Login, register, password reset
│   │   ├── (public)/         Marketing pages
│   │   ├── (protected)/      Auth-gated area
│   │   │   ├── @admin/       Admin dashboard slot
│   │   │   ├── @user/        User dashboard slot
│   │   │   └── layout.tsx    Permission-based slot picker
│   │   ├── api/              BetterAuth + health
│   │   ├── layout.tsx        Root layout + SEO
│   │   └── providers.tsx     Theme + Auth + Query
│   ├── components/
│   │   ├── shared/           Hero, logo, home sections
│   │   └── ui/               shadcn/ui primitives
│   ├── features/
│   │   ├── auth/             BetterAuth, RBAC, demo mode
│   │   ├── i18n/             next-intl config
│   │   ├── navigation/       Header + Sidebar
│   │   ├── site/             site.config.json + Zod parser
│   │   ├── theme/            Custom theme provider
│   │   └── users/            Example API + hooks
│   └── libs/                 env, api-client, logger, rate-limit, utils
└── package.json              scripts; Prettier + Commitlint config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key conventions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;features/&amp;lt;name&amp;gt;/&lt;/code&gt; — vertical slices&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;libs/&lt;/code&gt; — cross-cutting infra, no business logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;components/ui/&lt;/code&gt; — shadcn primitives; extend, don't fight the CLI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;schemas/&lt;/code&gt; — shared Zod schemas (e.g. API responses)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="out-of-the-box"&gt;Everything You Get Out of the Box&lt;/h2&gt;

&lt;p&gt;✅ Next.js 16 + React 19 (App Router, Server Components)&lt;br&gt;
✅ TypeScript 5.9 (strict)&lt;br&gt;
✅ Tailwind CSS v4&lt;br&gt;
✅ BetterAuth (email/password + optional Google OAuth)&lt;br&gt;
✅ Permission-based RBAC with parallel routes&lt;br&gt;
✅ next-intl (6 languages, RTL, type-safe, cookie-based)&lt;br&gt;
✅ T3 Env (Zod-validated server + client env vars)&lt;br&gt;
✅ TanStack Query + ofetch (&lt;code&gt;apiFetch&lt;/code&gt; + Zod parsing)&lt;br&gt;
✅ React Hook Form + Zod (auth forms + shared schemas)&lt;br&gt;
✅ SEO suite (OG, Twitter Cards, JSON-LD, sitemap, robots, manifest)&lt;br&gt;
✅ Custom theme provider (light / dark / system)&lt;br&gt;
✅ shadcn/ui (Radix + CVA + Tailwind)&lt;br&gt;
✅ Sentry (server + client instrumentation)&lt;br&gt;
✅ pino (structured server logging)&lt;br&gt;
✅ Optional Upstash rate limiting helpers&lt;br&gt;
✅ Vitest + React Testing Library&lt;br&gt;
✅ Playwright E2E&lt;br&gt;
✅ Lefthook + Commitlint&lt;br&gt;
✅ Knip (dead-code hygiene)&lt;br&gt;
✅ ESLint + Prettier&lt;br&gt;
✅ GitHub Actions CI + Playwright workflow&lt;br&gt;
✅ Docker + Docker Compose (&lt;code&gt;standalone&lt;/code&gt; output)&lt;br&gt;
✅ Demo mode (isolated &lt;code&gt;src/features/auth/demo/&lt;/code&gt;)&lt;br&gt;
✅ Health check (&lt;code&gt;GET /api/health&lt;/code&gt;)&lt;br&gt;
✅ Renovate + Vercel Analytics&lt;br&gt;
✅ Vercel one-click deploy&lt;/p&gt;




&lt;h2 id="who-should-use-this"&gt;Who Should Use This (and Who Shouldn't)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This is a good fit if you're building:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A SaaS product with multiple user roles&lt;/li&gt;
&lt;li&gt;An internationalized app (especially with RTL requirements)&lt;/li&gt;
&lt;li&gt;A frontend that consumes an existing API or BFF&lt;/li&gt;
&lt;li&gt;A project where you want auth, RBAC, i18n, and DX tooling on day one without inheriting a database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Probably not the right choice for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single-page landing site (more than you need)&lt;/li&gt;
&lt;li&gt;An app that needs a tightly-coupled database layer in the same repo (this is intentionally API-only)&lt;/li&gt;
&lt;li&gt;Enterprise RBAC with orgs, teams, and dynamic roles in the DB (start here, extend in your backend)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="contributing"&gt;Contributing&lt;/h2&gt;

&lt;p&gt;The project is fully open source and contributions are welcome:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork and branch from &lt;code&gt;main&lt;/code&gt; (&lt;code&gt;feat/...&lt;/code&gt;, &lt;code&gt;fix/...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm run check&lt;/code&gt; — it must pass&lt;/li&gt;
&lt;li&gt;Use Conventional Commits (Lefthook enforces this)&lt;/li&gt;
&lt;li&gt;Open a PR with a clear description&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🐛 &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/issues" rel="noopener noreferrer"&gt;Report a bug&lt;/a&gt; · ⭐ &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Star on GitHub&lt;/a&gt; · 🤝 &lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/pulls" rel="noopener noreferrer"&gt;Submit a PR&lt;/a&gt;&lt;/p&gt;




&lt;h2 id="final-thoughts"&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I built the first version because I was tired of repeating myself. Then I rebuilt it with feature-sliced folders, BetterAuth, type-safe env and i18n, parallel-route dashboards, and a DX pipeline (Lefthook, Knip, Vitest, Playwright) that matches what I actually run before every push.&lt;/p&gt;

&lt;p&gt;The goal was never the &lt;em&gt;biggest&lt;/em&gt; starter kit. It was the one I want on &lt;strong&gt;day one&lt;/strong&gt; of a SaaS frontend — and still trust on &lt;strong&gt;day one hundred&lt;/strong&gt;, with a backend I chose myself.&lt;/p&gt;

&lt;p&gt;If it saves you a week of glue code, it was worth open-sourcing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your biggest pain point when starting a new Next.js project?&lt;/strong&gt; Drop a comment — I'm always looking for improvements that stay frontend-first.&lt;/p&gt;

&lt;p&gt;Happy building. 🚀&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://nextjs-elite-boilerplate.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt; · 📦 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; · 🚀 &lt;strong&gt;&lt;a href="https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate/generate" rel="noopener noreferrer"&gt;Use Template&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://vercel.com/new/clone?repository-url=https://github.com/salmanshahriar/Nextjs-Elite-Boilerplate" rel="noopener noreferrer"&gt;Deploy on Vercel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>boilerplate</category>
      <category>saas</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
