This file gives AI assistants the rules needed to write correct code in this project.
For deep architectural explanations see docs/architecture.md.
React project template based on Feature-Sliced Design (FSD).
- React 18 + Vite + TypeScript (strict mode enabled)
- CSS Modules + Ant Design — styling and UI components
- Zustand — client-side state management
- TanStack Query (React Query) — server-state / async data fetching
- React Router v7 — client-side routing
- Vitest + jsdom — unit and component testing
@/ maps to src/.
- All cross-layer and cross-slice imports MUST use
@/. - Relative imports (
./,../) are only allowed within the same slice/segment.
// correct — cross-layer import
import { Button } from "@/shared/ui"
import { useAuthStore } from "@/features/auth/model"
// wrong — relative import crossing slice boundary
import { Button } from "../../shared/ui"Full reference:
docs/architecture.md
Layers (top → bottom). Each layer may only import from layers below it.
app ← can import: pages, widgets, features, entities, shared
pages ← can import: widgets, features, entities, shared
widgets ← can import: features, entities, shared
features ← can import: entities, shared
entities ← can import: shared
shared ← cannot import any other layer
A slice MUST NOT import from a different slice on the same layer. Imports between segments within the same slice are allowed.
// FORBIDDEN — feature importing another feature
import { getProfile } from "@/features/profile" // inside features/authWhen one entity must reference a type or value from another entity on the same layer, use the @x pattern instead of a direct slice import.
// src/entities/user/@x/order.ts — re-exports only what the order entity is allowed to use from user
export type { UserId } from "../model"Each slice contains segments (only create what is needed):
sliceName/
ui/ # React components
model/ # state, stores, hooks, types
api/ # API calls and query hooks
lib/ # utilities local to this slice
config/ # constants and configuration
index.ts # public API barrel — only export what consumers need
Code outside the slice must import from the index.ts barrel, never from internal files directly.
// Correct
import { LoginForm } from "@/features/auth"
// Wrong — imports an internal file directly
import { LoginForm } from "@/features/auth/ui/LoginForm"shared/
api/ # base HTTP client, interceptors
config/ # app-wide constants and env vars
lib/ # generic utilities and helpers
store/ # shared Zustand store utilities
ui/ # generic, reusable UI components
shared has zero business domain knowledge — no user, order, or other domain concepts.
// ❌ Default export
export default function UserCard() { ... }
// ❌ any type
const data: any = response.data
// ❌ Import Zustand or Axios directly — use shared wrappers
import { create } from "zustand" // use @/shared/store
import axios from "axios" // use @/shared/apiTests live next to the source file they test, named *.test.ts or *.test.tsx.
model/
authStore.ts
authStore.test.ts
Conventional Commits: <type>(<scope>): <description>
Types: feat, fix, docs, style, refactor, test, chore, perf, revert
feat(auth): add JWT refresh logic
fix(cart): prevent duplicate item entries
chore(deps): upgrade react-router to v7
Split changes into logically separate commits — do not mix code, tests, and docs in one commit.
- Stage selectively:
git add <specific-files>, notgit add -A - Commit order: code → tests → docs → config
# ✅ separate commits
git add src/features/auth/ && git commit -m "feat(auth): add login form"
git add src/features/auth/model/useAuthStore.test.ts && git commit -m "test(auth): add store tests"
# ❌ everything in one commit
git add -A && git commit -m "feat(auth): add login form, tests, and docs"
Full reference:
.github/skills/git-workflow/SKILL.md
Branching: Git Flow — main (production) + development (integration) + short-lived feat/, fix/, hotfix/, release/ branches.
Branch naming: <type>/<scope>-<short-description> (e.g., feat/auth-jwt-refresh)
Merge strategy: Squash Merge for features → development; Merge Commit for releases/hotfixes → main.
Protected branches: main and development — no direct push, PR + 1 approval required.
Versioning: v<MAJOR>.<MINOR>.<PATCH> (Semantic Versioning)
Repository: Bitbucket · CI/CD: Jenkins · Code quality: SonarQube
Language: Thinking and response text follow the user's language. Code, comments, documentation, commit messages, and PR content are always in English.
Branch-first: Always create a feature branch before writing any code — never commit directly to main or development.
Commit/PR review: Before executing git commit or creating a PR, display the proposed message in the response text, then ask the user for confirmation using the environment's question/ask tool (e.g., vscode_askQuestions in VS Code, question in opencode) with confirm/edit/cancel options. Never execute without tool-based confirmation. Use single-select when the user must choose exactly one option (e.g., confirm/edit/cancel or yes/no); use multi-select when the user needs to choose multiple items (e.g., files to stage, issues to fix).
Iterative workflow: If new changes arise after a commit, re-enter the workflow from the appropriate step — assess, stage, show message, commit. Never skip steps.
Session end gate: After completing any task or yielding control, always ask the user about the next action via the environment's question/ask tool. Include context-appropriate options and a "pause/stop" choice. This applies after every commit, push, PR creation, or code change — not only at session end.
FSD import rules are enforced by eslint-plugin-boundaries. Violations block commits via pre-commit hooks — fix them before committing.