Skip to content

base-codings/next-js-base

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Next.js Base Template

A production-ready Next.js 15 starter template with opinionated architecture, type-safe i18n, and a curated UI kit. Designed to be cloned and extended.

Next.js React TypeScript Tailwind


Features

  • Next.js 15 App Router with Turbopack dev server
  • React 19 with Server Components + Server Actions
  • Tailwind CSS v4 with @theme inline + CSS-variable theming
  • 26 base UI components wrapping Radix UI primitives
  • Type-safe i18n via Lingui with Edge-runtime middleware locale detection
  • TanStack Query for server state + Zustand for client state
  • React Hook Form + Zod for form validation
  • Module pattern for page-level code organization
  • Edge middleware with Accept-Language resolution, cookie persistence, CDN-safe Vary headers
  • ESLint + Prettier + Husky pre-commit pipeline

Tech Stack

Layer Stack
Framework Next.js 15.5 (App Router) + React 19.2
Language TypeScript 5 (strict mode)
Styling Tailwind CSS v4 + class-variance-authority + tailwind-merge
UI Primitives Radix UI + Base UI React
Icons lucide-react
Fonts Roboto (self-hosted)
i18n Lingui 5.4 (en, nl, zh — expand as needed)
Server State TanStack Query v5
Client State Zustand v5
Forms React Hook Form + Zod + @hookform/resolvers
HTTP Client Axios (with auth interceptor stub)
Animations motion + tailwindcss-animate
Toasts sonner
Dates dayjs
Package Manager pnpm

Prerequisites

  • Node.js ≥ 20
  • pnpm ≥ 8

Getting Started

pnpm install
pnpm dev

Open http://localhost:3000.

Environment Variables

Copy .env.example to .env.local (create as needed):

NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:8000

Project Structure

src/
├── app/                     # Next.js App Router routes
│   ├── layout.tsx
│   ├── page.tsx             # Composes <HomeModule />
│   ├── providers.tsx
│   └── preload-resources.tsx
├── apis/                    # HTTP client + domain-based API layer
│   ├── axios.ts             # Shared axios instance
│   ├── helper.ts            # handleApiError, encodeQueryData
│   └── _example/            # Domain scaffold template
├── assets/                  # Fonts + static icons
├── components/
│   ├── base/                # 26 primitives (button, input, dialog, ...)
│   ├── layout/              # Header, Footer
│   └── shared/              # Cross-module reusable widgets
├── core/                    # Configs, constants, enums, types
├── hooks/                   # Global custom hooks (camelCase)
├── modules/                 # Page-level modules (1:1 with app/ routes)
│   └── home/
│       ├── home.module.tsx  # Entry (composes UI + script)
│       ├── home.ui.tsx      # Pure UI
│       ├── home.script.ts   # Logic hook
│       ├── components/      # Module-local components
│       ├── widgets/         # Module-local 3-file widgets
│       ├── hooks/           # Module-local hooks
│       └── utils/           # Module-local utilities
├── providers/               # Top-level React providers
│   ├── layout.provider.tsx
│   ├── lingui.provider.tsx
│   └── react-query.provider.tsx
├── stores/                  # Zustand stores
├── styles/                  # Split CSS (globals, reset, animations, themes)
│   ├── globals.css
│   └── themes/light.css
├── translations/            # Lingui catalogs + client/server helpers
├── utils/                   # Pure utility functions
│   ├── generic.ts           # cn() class merger
│   └── validation/regex.ts
└── middleware.ts            # Edge locale resolution

Architectural conventions are enforced by docs/code-standards.md and docs/design-guidelines.md.

Scripts

Command Purpose
pnpm dev Start Turbopack dev server (extracts + compiles translations first)
pnpm build Production build with formatting + translations pipeline
pnpm start Run production server
pnpm lint ESLint check
pnpm lint:fix ESLint auto-fix on ./src
pnpm format Prettier write on entire repo
pnpm translations:extract Extract <Trans> + msg\`` usages into PO files
pnpm translations:compile Compile PO files to runtime JS
pnpm translations Extract + compile

Internationalization

Supported locales: en, nl, zh (configured in lingui.config.ts + src/translations/languages.ts).

Add a new language

  1. Add locale code to lingui.config.ts (locales array) and src/translations/languages.ts
  2. Add entry to SUPPORTED_LOCALES in src/core/constants/common.constant.ts
  3. Run extraction:
    pnpm translations:extract
  4. Translate the generated src/translations/locales/{locale}/messages.po
  5. Compile:
    pnpm translations:compile

Locale Resolution Flow

Browser request
  ↓
Middleware (Edge) reads cookie NEXT_LINGUI_LOCALE
  ↓ (if missing/invalid) parse Accept-Language header
  ↓ pick best-matching SUPPORTED_LOCALES (full-tag → primary-subtag → default)
  ↓ writes request.cookies + response.cookies (same-request propagation)
  ↓ sets Vary: Accept-Language, Cookie (CDN-safe)
  ↓
Server component (providers.tsx) reads resolved cookie → loads messages

Module Pattern

Each app/ route maps 1:1 to a folder in src/modules/. The entry file uses .module.tsx suffix:

// src/app/page.tsx
import { HomeModule } from '@/modules/home/home.module'
export default function Page() {
    return <HomeModule />
}
// src/modules/home/home.module.tsx
'use client'
import { useHomeScript } from './home.script'
import { Home } from './home.ui'

export function HomeModule() {
    const state = useHomeScript()
    return <Home {...state} />
}
  • .module.tsx — entry, composes UI + script
  • .ui.tsx — pure rendering, receives props
  • .script.ts — business logic hook

Module-local components/, widgets/, hooks/, utils/ keep concerns scoped. Promote to src/components/shared/ when reused across modules.

Rule: Never place .module.css next to .module.tsx — Next.js CSS Modules collision.

Base UI Components

26 primitives under src/components/base/, each in its own folder with a 2-line index.ts re-export:

badge · button · calendar · checkbox · container · datepicker · dialog
dropdown-menu · h-stack · input · input-group · label · popover
radio-group · select · sheet · show · skeleton · slider · switch
table · tabs · textarea · toaster · tooltip · v-stack

Import by folder name:

import { Button } from '@/components/base/button'
import { Dialog, DialogTrigger, DialogContent } from '@/components/base/dialog'

Styled via design tokens in src/styles/themes/light.css; never use raw color/spacing values in components.

API Layer

Domain-based organization:

apis/
├── axios.ts            # Shared instance with auth interceptor stub
├── helper.ts           # handleApiError, encodeQueryData
├── _example/           # Template — delete or replace
│   ├── types.ts        # Domain types
│   ├── requests.ts     # fetch() wrappers
│   └── queries.ts      # useQuery/useMutation hooks
└── {your-domain}/
    ├── types.ts
    ├── requests.ts
    └── queries.ts

Error handling via handleApiError(error) returns a user-safe Error with translated DEFAULT_ERROR_MESSAGE.

Deployment

Vercel (recommended)

Deploy with Vercel

Push to GitHub and import into Vercel. Set NEXT_PUBLIC_* env vars in the dashboard.

Self-hosted

pnpm build
pnpm start

See Next.js deployment docs for Docker, Node, or other targets.

Documentation

Contributing

  1. Create a feature branch from dev
  2. Follow conventions in docs/code-standards.md
  3. Run pnpm lint && pnpm build before committing
  4. Open a PR with conventional commit title (feat:, fix:, refactor:, etc.)

License

Private — adapt for your project.

About

Production-ready Next.js 15 boilerplate with Tailwind v4, Radix UI, Lingui i18n and module-pattern architecture — ship more fast

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors