The Problem That Kept Me Up at Night
You know that feeling when you start a new Next.js project and spend the first week just setting things up? Authentication, internationalization, role management, SEO configuration... By the time you're done with the boilerplate, you've lost all that initial excitement.
What you get in one line: Type-safe i18n with RTL → NextAuth + Google OAuth → RBAC with parallel routes → SEO (sitemap, robots, manifest) → Dark mode → ESLint + Prettier → Vitest + Playwright → shadcn/ui → One config file. Production-ready.
I've been there. Too many times.
After launching my third SaaS project this year, I realized I was copy-pasting the same setup code over and over. So I decided to do something about it.
What I Built
Meet my production-ready Next.js boilerplate: not just another "hello world" starter template, but a fully-featured foundation that handles all the boring stuff so you can focus on building your actual product.
Important Links:
🔗 Live Demo | 📦 GitHub Repo | 🚀 Use this template | Deploy on Vercel
Why This Boilerplate is Different
🌍 Real Internationalization (Not Just a Dictionary)
I'm talking about type-safe translations that catch errors at compile time. No more broken translations in production because you typo'd a key.
Here's what makes it special:
- Three languages out of the box: English, বাংলা (Bengali), and العربية (Arabic)
- RTL support that actually works: Arabic layouts automatically flip to right-to-left
- Dead-simple language switching: One click, zero page reload
- Type-safe with TypeScript: Your IDE will tell you when a translation is missing
// TypeScript knows all your translation keys
t('navigation.home') // ✅ Works
t('navigation.homer') // ❌ Compile error - typo caught!
🔐 Role-Based Access Control That Scales
Most tutorials show you basic auth and call it a day. But what about when you need different dashboards for users and admins? Or when you want to add a "Moderator" role later?
I used Next.js 15's parallel routes to make this painless:
app/
(protected)/
@admin/ # Admin-only views
dashboard/
@user/ # User views
dashboard/
layout.tsx # Smart routing logic
The layout automatically shows the right dashboard based on the user's role. No messy conditionals scattered everywhere. Want to add a new role? Just create a new parallel route folder. That's it.
🎨 A Design System That Doesn't Suck
I'm using shadcn/ui because:
- Components are copy-paste ready (no bloated dependencies)
- Full TypeScript support
- Accessible by default (WCAG compliant)
- Easy to customize without fighting CSS
Plus next-themes for light/dark mode with system preference detection and a manual toggle.
🔧 ESLint That Actually Helps (Not Annoys)
Let's be honest - most ESLint configs are either too strict or too loose. I spent time configuring rules that:
- Catch real bugs (unused variables, missing dependencies, potential null references)
- Enforce consistency (import order, naming conventions, formatting)
- Don't get in your way (no annoying warnings for things that don't matter)
- Work with Next.js 15 (proper App Router support, server component rules)
The config includes:
-
eslint-config-next- Official Next.js rules - TypeScript-specific linting
- Import sorting and organization
- Best practices for React hooks
- Accessibility checks (a11y)
Prettier is wired up too (Tailwind plugin, format on save in .vscode/settings.json). Run npm run lint and npm run prettier:fix for consistent, clean code.
📊 SEO Configuration That's Actually Usable
Instead of hardcoding metadata everywhere, I created a single JSON configuration file that handles:
- Open Graph tags
- Twitter cards
- Structured data (JSON-LD)
- Multi-language meta tags
- Canonical URLs
- Dynamic sitemap generation
Just edit one file:
{
"appName": "Your App",
"title": "Your Title",
"description": "Your Description",
"domain": "https://yoursite.com",
"keywords": ["your", "keywords"],
"social": {
"twitter": "@yourhandle"
}
}
Done. SEO handled. The same config drives sitemap (sitemap.ts), robots.txt (robots.ts), and manifest (manifest.ts).
🧪 Testing & CI
-
Unit and component tests: Vitest + React Testing Library. Run
npm run testornpm run test:watch;npm run test:coveragefor coverage. -
E2E: Playwright in
e2e/. Runnpm run e2e(dev server starts automatically);npm run e2e:uifor the UI. Usenpm run e2e:webkitfor WebKit-only (e.g. to save disk). -
CI: GitHub Actions –
.github/workflows/check.ymlruns lint, Prettier, tests, and build on push/PR;.github/workflows/playwright.ymlruns E2E.
🔑 Authentication (NextAuth.js + Google OAuth)
Auth is built in with NextAuth.js. You get:
-
Google OAuth – enable by setting
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET, andNEXT_PUBLIC_GOOGLE_AUTH_ENABLED=truein.env -
Custom login page at
/auth/loginwith optional "Sign in with Google" -
Admin role by email – set
AUTH_ADMIN_EMAILS=admin@yourdomain.com(comma-separated); those Google accounts get the admin role automatically -
JWT session with role and user id; redirect to
/dashboardafter sign-in
Copy .env.example to .env, add your secrets, and you're done.
🏥 Health Check
GET /api/health returns { status: "ok" } for load balancers and Kubernetes probes.
How to Get Started (The Real Way)
Step 1: Clone and Install
# Grab the code
git clone https://github.com/salmanshahriar/nextjs-boilerplate-production-ready.git
cd nextjs-boilerplate-production-ready
# Install dependencies (use whatever you prefer)
npm install
# or bun install / yarn install / pnpm install
Step 2: Configure Your Project
This is where most boilerplates leave you hanging. Not this one.
Edit lib/config/app-main-meta-data.json:
{
"appName": "My Awesome SaaS",
"title": "Revolutionary Product That Does X",
"description": "We help Y achieve Z",
"domain": "https://myawesomesaas.com",
"organization": {
"name": "My Company",
"email": "hello@mycompany.com"
},
"social": {
"twitter": "@myhandle",
"github": "https://github.com/myhandle"
}
}
That's your entire brand configuration. One file.
Step 3: Customize Your Languages (Optional)
Want to add Spanish? Here's how:
- Create
locales/es.jsonwith the same structure aslocales/en.json:
{
"common": { "appName": "Mi App", ... },
"navigation": {
"home": "Inicio",
"about": "Acerca de"
}
}
- Update
lib/config/app-main-meta-data.json:
{
"languages": {
"supported": ["en", "bn", "ar", "es"],
"locales": {
"es": {
"code": "es",
"name": "Spanish",
"nativeName": "Español",
"locale": "es_ES",
"direction": "ltr"
}
}
}
}
- In
lib/i18n/get-translations.ts, importes.jsonand addesto thetranslationsobject. If you use strict translation keys, add the new locale to theTranslationKeysunion inlib/i18n/types.ts.
Done. Your app now speaks Spanish.
Step 4: Set Up Your Roles
The boilerplate comes with User and Admin roles. To add more:
- Create a new parallel route folder:
mkdir -p app/(protected)/@moderator/dashboard
Add your pages inside that folder
Update
app/(protected)/layout.tsxto handle the new role:
if (currentUser?.role === 'moderator') return moderator
That's genuinely all you need to do.
Step 5: Run It
npm run dev
Open http://localhost:3000 and see your fully-configured app running.
Available Scripts
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Production build |
npm run start |
Start production server |
npm run lint |
Run ESLint |
npm run lint:fix |
Fix ESLint errors |
npm run test |
Unit tests (Vitest) |
npm run test:watch |
Unit tests in watch mode |
npm run test:coverage |
Tests with coverage |
npm run e2e |
Playwright E2E tests |
npm run e2e:ui |
Playwright with UI |
npm run e2e:webkit |
E2E in WebKit only |
npm run prettier |
Check formatting |
npm run prettier:fix |
Fix formatting |
Step 6: Environment (First-Time Setup)
Copy .env.example to .env. Set NEXT_PUBLIC_APP_URL if you need to override the site URL (e.g. in production). For Google sign-in: set NEXTAUTH_URL, NEXTAUTH_SECRET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, then NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true. Optionally set AUTH_ADMIN_EMAILS=admin@yourdomain.com so those emails get the admin role.
Prerequisites
- Node.js 18.17 or later
- npm, yarn, pnpm, or bun
The Project Structure (Explained for Humans)
app/
(protected)/ # Routes behind auth
@admin/ # Admin-only pages
@user/ # User pages
layout.tsx # Role-based routing
api/ # API routes
auth/[...nextauth]/ # NextAuth handler
health/ # GET /api/health → { status: "ok" }
auth/login/ # Login page
unauthorized/ # 403-style page
layout.tsx # Root layout (theme, i18n)
page.tsx # Landing page
not-found.tsx # 404
manifest.ts # PWA manifest from config
robots.ts # Robots.txt from config
sitemap.ts # Dynamic sitemap from config
components/
ui/ # shadcn/ui
layout/ # Header, sidebar, theme toggle
language-switcher.tsx
locales/
en.json, bn.json, ar.json
lib/
auth/ # NextAuth options, session, auth context
config/
app-main-meta-data.json
site.ts # baseUrl, supportedLocales
i18n/
get-translations.ts
language-context.tsx
use-translations.ts
types.ts
utils.ts
e2e/ # Playwright E2E tests
.github/workflows/ # CI: check.yml, playwright.yml
What You Get Out of the Box
✅ Next.js 15 with App Router and Server Components
✅ TypeScript (strict mode)
✅ Tailwind CSS
✅ ESLint and Prettier (Next.js, TypeScript, a11y, format on save in .vscode)
✅ NextAuth.js with optional Google OAuth and admin-by-email
✅ i18n with type safety and RTL (en, bn, ar)
✅ RBAC with parallel routes (User / Admin)
✅ SEO from one JSON config (metadata, sitemap, robots, manifest)
✅ next-themes for dark mode (system + manual toggle)
✅ shadcn/ui (accessible, customizable)
✅ Vitest + React Testing Library for unit/component tests
✅ Playwright for E2E in e2e/
✅ GitHub Actions for lint, format, test, build and E2E
✅ Health check at GET /api/health
✅ Vercel-ready (one-click deploy from the repo)
Real Talk: When Should You Use This?
Perfect for:
- SaaS products with multiple user types
- International applications
- MVPs that need to look professional
- Projects where you want to ship fast
Maybe not ideal for:
- Simple landing pages (too much infrastructure)
- Projects with very specific auth requirements (you'll need to customize heavily)
- Apps that don't need i18n or role management
What I Learned Building This
- Parallel routes are underrated: They make role-based routing so much cleaner than conditional rendering
- Type-safe i18n is worth the setup: Catching translation bugs at compile time saves hours of debugging
- JSON configuration > hardcoded values: When you can change your entire SEO strategy by editing one file, you move faster
- Boilerplates should be opinionated: Too many options = decision fatigue. I made the tough choices so you don't have to
Contributing & Support
Found a bug? Want to add a feature? The repo is fully open source:
🐛 Report issues
⭐ Star on GitHub
🤝 Submit a PR
Final Thoughts
I built this because I got tired of setting up the same infrastructure for every project. If you're launching a product and don't want to spend two weeks on boilerplate, give it a try.
It's saved me probably 30+ hours across my last three projects. Maybe it'll help you too.
What's your biggest pain point when starting a new Next.js project? Drop a comment below - I'm always looking to improve this.
Happy building! 🚀
Links:
🔗 Live Demo | 📦 GitHub Repo | 🚀 Use this template | Deploy on Vercel

Top comments (2)
This is exactly what the dev community needed! Can’t wait to try it out — the 30-minute ship time sounds like a dream
thanks for your words! i happy to help you!