Skip to content

Latest commit

 

History

History
144 lines (106 loc) · 6.88 KB

File metadata and controls

144 lines (106 loc) · 6.88 KB

React.js Template

Starter template for React apps: FSD, TypeScript, Vite. Minimal dependencies, production-ready build and Docker deploy.

Stack

  • React 19 + TypeScript (strict)
  • Vite 8 + @vitejs/plugin-react — dev server and build
  • TanStack Router (+ devtools in dev) — routing (app/router: root-route, routes, shared NotFound / ErrorInterception defaults)
  • TanStack Query — server state and cache
  • Zustand — client state (in dependencies; wire stores in slices when needed)
  • i18next + react-i18next — i18n (app/providers/i18n-provider, useTranslation() in UI)
  • Valibot — validation (env, component props, API shapes)
  • Ky — HTTP client
  • SASS/SCSS + LightningCSS — styles (CSS pipeline)
  • Jest + Testing Library — tests
  • ESLint + Stylelint + Steiger (FSD) + Prettier + Commitlint + Husky — lint and commits
  • Docker + NGINX — deploy

Structure (FSD)

src/
├── app/
│   ├── layouts/           # e.g. root-layout/ (+ co-located *.schema.ts)
│   ├── providers/         # i18n-provider, query-client-provider, router-provider (kebab-case folders)
│   ├── router/            # root-route, routes, router factory
│   ├── locales/           # app-wide copy (en.json, ru.json, …)
│   └── styles/            # global SCSS entry and tokens
├── pages/                 # route screens (kebab-case slices: home, not-found, error-interception, …)
├── widgets/               # cross-page blocks (e.g. navigation — header/footer)
├── features/              # user-facing flows (empty stubs ready for slices)
├── entities/              # domain pieces (empty stubs ready for slices)
└── shared/                # UI kit, api, config (validated env), lib, assets/locales

Imports only “down”: app → pages → widgets → features → entities → shared.

Slices under pages/, widgets/, entities/, and features/ use kebab-case folder names. Each slice has model/ (schemas, optional locales/ for copy, optional constants/store). Typical layout: ui/<slice>/<slice>.tsx, model/schemas/<slice>.schema.ts, optional model/locales/en.json (and other languages), and optional model/constants.ts / model/store.ts. The slice root index.ts is the public API for that slice. In app/ and shared/ui, schemas sit next to the .tsx file (no model/ under shared/ui). Domain HTTP + TanStack Query for entities/features lives in slice api/ when you add it — see AGENTS.md and .cursor/rules/api-contracts.mdc.

Internationalization (i18n)

  • Slices (pages, widgets, features, entities): put locale files in model/locales/ (en.json, ru.json, …), next to model/schemas/ — not a separate i18n/ at the slice root.
  • Shared kit copy: shared/assets/locales/. App-wide defaults: app/locales/.
  • i18n-bootstrap.ts globs those paths (plus app/*/model/locales for any future app subfolders with model), deep-merges per language, registers under i18next’s default translation namespace. In UI: useTranslation() once, dot keys (t("navigation.header.home"), …). Prefer kebab-case top-level keys in each JSON file (navigation, home, …) — see AGENTS.md and .cursor/rules/fsd-i18n.mdc.

Where to put code: layer questions

Before adding code, ask yourself in order:

  1. App — is this app init, routing, providers, global styles, or app-wide config?
  2. Pages — is this a full page (screen) for one route/URL?
  3. Widgets — is this a large self-contained UI block used on multiple pages or one of several such blocks on one page?
  4. Features — is this a user action with business value, reused in different places (form, action button, flow)?
  5. Entities — is this a business entity from the domain (model, entity representation without binding to one action)?
  6. Shared — is the code not business-bound: utils, UI kit, API client, config, i18n?

The first match defines the layer. If none fit — clarify boundaries (don’t bloat entities; non-reused code can stay on the page).

Requirements

  • Node.js ≥ 24.12
  • pnpm (recommended)

Install and run

git clone <repo-url>
cd reactjs-template
pnpm install
pnpm run dev

The app will open at the URL from the output.

Scripts

Command Description
pnpm run dev Dev server with HMR (--host)
pnpm run build Production build (runs check first via prebuild)
pnpm run build:compress Build + gzip/brotli for static assets
pnpm run build:analyze Build + bundle size report
pnpm run serve Preview production build locally
pnpm run check Typecheck + lint + tests
pnpm run test Jest
pnpm run lint ESLint + Stylelint + Steiger (FSD)
pnpm run lint:eslint ESLint only (with autofix)
pnpm run lint:styles Stylelint for css / sass / scss
pnpm run lint:fsd Steiger FSD boundaries
pnpm run format Prettier (code and listed formats)
pnpm run deploy Deploy dist to GitHub Pages

Environment variables

Copy .env.example to .env and adjust if needed. Values are validated at startup with Valibot in src/shared/config/env.ts; invalid configuration throws before the app renders.

  • VITE_API_URL — base API URL (must be a valid URL)
  • VITE_I18N_DEBUGtrue or false — i18n debug logging
  • VITE_I18N_FALLBACK_LNG — fallback language code
  • VITE_I18N_STORAGE_KEY — key for persisting language in storage

Docker

docker build -t reactjs-template .
docker run -p 80:80 reactjs-template

Build uses build:compress; static assets are served via NGINX (config in nginx.conf).

Code standards

  • Strict typing, no any
  • FSD: layer boundaries, import direction, Steiger in CI/local
  • Component props: Valibot schemas + explicit ComponentNameProps (see AGENTS.md and .cursor/rules/)
  • Prefer arrow functions, SOLID and KISS
  • No comments or dead code in prod

Detailed rules in .cursor/rules/ and AGENTS.md.

Commitlint

Commits are checked with Conventional Commits (Husky + commitlint). Format:

<type>(<scope>): <subject>
  • type: feat, fix, docs, style, refactor, perf, test, chore, ci, build.
  • scope (optional): area of change, e.g. auth, header, deps.
  • subject: short description in imperative mood, no period at end; up to 72 chars.

Examples: feat(auth): add login form, fix(api): handle 404, chore(deps): update vite.

Contacts

License

Template is free to use, modify and distribute.