A production-minded React + TypeScript starter on Next.js App Router. Domain modules keep the product scalable; the demo app stays small: a protected product catalog backed by DummyJSON.
Use it as a template for a new Next.js app: cookie session, RSC data loading, Server Actions, URL-driven filters, i18n, and a full UI kit are already wired.
- Session-based sign-in with httpOnly access/refresh cookies and silent refresh in
proxy.ts - Current user (
GET /auth/me) and role-gated catalog writes (admin/moderator) - Product catalog: search, sort, pagination, details, create / update / delete
- DummyJSON does not persist writes — on the real API, created rows vanish after revalidation; the e2e mock keeps them in memory
- Theme (light/dark) and locale (Russian / English) with
/ruand/enprefixes - Typed HTTP client, Zod on API boundaries, react-hook-form on screens
- Storybook for
src/ui, Vitest + MSW, Playwright e2e against a local mock API
| Area | Choice |
|---|---|
| UI | React 19, Tailwind CSS 4, shadcn / Base UI |
| Framework | Next.js 16 App Router, RSC |
| Mutations | Server Actions + cache tags |
| Client UI state | Zustand |
| Forms | react-hook-form + Zod |
| i18n | next-intl |
| Quality | ESLint (module boundaries), Prettier, Vitest, Playwright, Storybook 10 |
Package manager is pnpm only (see packageManager in package.json). Node.js 22+ is required.
pnpm install
cp .env.example .env
pnpm dev.env.example points at DummyJSON:
API_BASE_URL=https://dummyjson.com
APP_ENV=development
Open the app, sign in, and you land on the catalog (/ru by default).
| Username | Password |
|---|---|
emilys |
emilyspass |
These are DummyJSON demo users. Other public DummyJSON accounts work the same way.
| Command | What it does |
|---|---|
pnpm dev |
Next.js dev server |
pnpm build |
Production build |
pnpm start |
Serve the production build |
pnpm typecheck |
tsc --noEmit |
pnpm lint / pnpm lint:fix |
ESLint |
pnpm format / pnpm format:check |
Prettier |
pnpm test |
Vitest (unit / integration) |
pnpm test:watch |
Vitest watch mode |
pnpm test:coverage |
Vitest with coverage |
pnpm e2e |
Playwright |
pnpm e2e:install |
Playwright Chromium + OS deps |
pnpm storybook |
Storybook on port 6006 |
app/ is routing only. Product code lives in src/modules/{auth,user,catalog,shell}, the design system in src/ui, shared infrastructure in src/lib. Modules never import each other; pages and layouts compose them.
- Create
src/modules/<name>/{index.ts, ...}. - Export only the public API from
index.ts. - Import it from
app/(or fromui/lib— never from another module). - Run
pnpm lint— cross-module and deep imports fail the boundary rules.
Husky runs lint-staged and commitlint. CI runs typecheck, lint, format, unit tests, build, Storybook build, and e2e.
If this project helps you, optional tips in USDT (Tron / TRC-20) are welcome:
Address (TRC-20 / Tron):
TNrPGfU3HqtfMPmmhdvrJsQng7Ck9fian4
Send only USDT over the Tron network to this address; using other chains can mean lost funds.
Ivan Khludov — ivan.khludov.dev@gmail.com
Licensed under the MIT License.
