Initial commit

This commit is contained in:
Igor Martyniuk
2026-06-25 15:53:49 +03:00
commit 1bb0b7e68a
1517 changed files with 218469 additions and 0 deletions
@@ -0,0 +1,392 @@
# CRUX React Frontend Architecture
This guide describes the recommended React frontend architecture for apps in the CRUX monorepo.
Its main goal is to make frontend development easier, more structured, and consistent across teams, so that every developer can write and understand each other's code quickly.
## Table of Contents
- [Base Concepts](#base-concepts)
- [Disclaimer](#disclaimer)
- [Core Principles](#core-principles)
- [Recommended Layering](#recommended-layering)
- [Architecture Scope](#architecture-scope)
- [Layer Dependency Rules](#layer-dependency-rules)
- [Entities Layer](#1-entities-layer)
- [Data Layer (Data Access Layer)](#2-data-layer-data-access-layer)
- [Purpose](#purpose)
- [Responsibilities](#responsibilities-2)
- [Rules and Guidelines](#rules-and-guidelines)
- [Infrastructure Layer](#infrastructure-layer)
- [Reference Data Layer](#reference-data-layer)
- [Providers Layer](#3-providers-layer)
- [Pages Layer](#4-pages-layer)
- [View Layer](#5-view-layer)
- [view/components/](#viewcomponents)
- [view/forms/](#viewforms)
- [view/widgets/](#viewwidgets)
- [Shared Layer](#6-shared-layer)
- [Responsibilities](#responsibilities-4)
- [Rules](#rules-2)
- [Full documentation](#full-documentation)
## Base Concepts
- **Purpose:** Provide a shared frontend foundation with predefined packages, utilities, and patterns for React apps and frontend modules in this monorepo.
- **Goals:**
- Reduce boilerplate code.
- Standardize folder structure, file naming, and coding practices in the company context.
- Assist in onboarding of new developers.
- **Included:**
- Preconfigured `React` + `TypeScript` setup.
- Common utilities and helper functions.
- Shared UI components, hooks, and state management helpers.
- Integrated i18n, form validation, and API utilities.
## Disclaimer
This architecture guide is intended as a **recommendation**, not a strict rulebook. **Feel free to adapt and modify it based on your team’s needs and project context**.
Key points to keep in mind:
1. **Maintainability comes first**.
The main goal of this structure is to help someone new to the project quickly understand where to make changes.
It’s about finding the right place to touch the code now, rather than strictly following a pattern for its own sake.
**Ultimately, the main goal is to make development easier for everyone**
2. **Naming debates are inevitable**.
Any architecture guide may spark discussions about file, folder, or function naming. Use this guide as a reference, but remember that practicality and clarity are more important than strict adherence.
3. **Flexibility is allowed**.
- You can adjust layers, module structure, or naming conventions if it improves readability or reduces complexity.
- New patterns or exceptions can be added as the project evolves.
In short: this guide exists to make the project easier to understand and maintain, not to create unnecessary friction. Use judgment and prioritize clarity over rigid consistency.
---
Цей посібник з архітектури є **рекомендацією**, а не суворим зводом правил. **Не соромтеся адаптувати та змінювати його відповідно до потреб вашої команди та контексту проєкту**.
Ключові моменти, які варто мати на увазі:
1. **Насамперед — зручність підтримки**.
Головна мета цієї структури — допомогти новому учаснику проєкту швидко зрозуміти, де вносити зміни.
Йдеться про те, щоб знайти правильне місце в коді просто зараз, а не сліпо дотримуватися патерну заради самого патерну.
**Зрештою, головна мета — зробити розробку простішою для всіх.**
2. **Дискусії щодо назв неминучі**.
Будь-який посібник з архітектури може спровокувати суперечки щодо назв файлів, папок або функцій. Використовуйте цей посібник як орієнтир, але пам'ятайте, що практичність і зрозумілість важливіші за суворе дотримання правил.
3. **Гнучкість допускається**.
- Ви можете коригувати шари, структуру модулів або угоди щодо найменування, якщо це покращує читабельність або зменшує складність.
- У міру розвитку проєкту можна додавати нові патерни або винятки.
Коротко: цей посібник існує для того, щоб проєкт був зрозумілішим і простішим у підтримці, а не для того, щоб створювати зайві труднощі. Керуйтеся здоровим глуздом і надавайте перевагу ясності, а не жорсткій послідовності.
## Core Principles
1. Blocks are composable and isolated
- Each block (component, form, widget) has a single responsibility.
- Higher-level blocks (widgets, pages) compose lower-level blocks.
2. Data vs. UI separation
- `data` handles API, state, and business data.
- `view` handles UI and interaction.
- No API logic in UI components — UI calls hooks from `data`.
3. Entities are global types/interfaces
- Placing them in `entities`.
- Any block (data hook, form, widget, page) can use these.
4. Shared
- shared/ = globally reusable components, hooks, utilities.
5. Infrastructure
- infrastructure/ = app-wide technical adapters such as HTTP clients, React Query, storage adapters, and formatting service wrappers.
6. Reference data
- refdata/ = app-wide API-backed lookup datasets shared by multiple modules.
## Recommended Layering
```plaintext
src/
├── data/ # API, react-query hooks, DTOs
├── entities/ # global types and interfaces
├── infrastructure/ # technical adapters: HTTP, query, storage, error handling
├── providers/ # global providers (router, query, session, i18n, theme)
├── refdata/ # API-backed common reference datasets
├── shared/ # reusable global components, hooks, libs, assets, styles
├── view/ # UI layer (blocks)
│ ├── components/ # Feature-level reusable components (ProductCard, LoginButton, VehicleSearchInput)
│ ├── forms/ # smart form components (ProductForm, UserForm)
│ └── widgets/ # composed smart, multi-entity components (DashboardStatsWidget, UserProfileWidget)
└── pages/ # route-level pages
```
## Architecture Scope
The layer structure can be used at three levels:
| Scope | Example | Meaning |
| --------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| App-level architecture | `apps/admin/src/app`, `apps/admin/src/shared` | Global app shell, providers, routing, layout, infrastructure, reusable app-wide building blocks. |
| Core module architecture | `apps/admin/src/core/FileManager` | Built-in product modules shipped with the admin template. Each large core module can own its own `data`, `entities`, `providers`, `pages`, `view`, and `shared`. |
| Project module architecture | `apps/admin/src/modules/*` | Generated or project-specific modules. Each module should follow the same layer rules inside its own folder when it becomes more than a simple page. |
For small modules, do not create empty layers only to match the template. Add a layer when the module has real ownership for that layer.
### Admin App Interpretation
`apps/admin` is a reusable admin panel template, not a simple single-purpose React app.
The app shell owns cross-cutting concerns:
- routing and route registration
- global providers
- layouts
- i18n setup
- shared UI
- technical infrastructure
- module registration
Admin app infrastructure that is shared by every module lives in `apps/admin/src/infrastructure`.
Examples include HTTP clients, React Query helpers, storage adapters, and error normalization.
Admin-wide API-backed reference datasets live in `apps/admin/src/refdata`.
Examples include country lists, common option datasets, and other reusable data that comes from the backend but is not owned by one feature module.
Each feature module owns its feature concerns:
- API calls and query hooks in module `data`
- module domain types in module `entities`
- module-local contexts and stores in module `providers`
- route-level screens in module `pages`
- module UI in module `view`
- module-only helpers in module `shared`
If a helper or component becomes useful across multiple modules, move it upward to `apps/admin/src/shared` or a package under `packages/`.
## Layer Dependency Rules
Each layer has defined set of layers it is allowed to import from.
Imports must only flow **downward** — a lower layer never knows about a higher one.
Violating this creates circular dependencies and couples layers that should be independent.
```mermaid
graph TD
pages["pages/"]
view["view/"]
data["data/"]
providers["providers/"]
infrastructure["infrastructure/"]
refdata["refdata/"]
entities["entities/"]
shared["shared/"]
pages --> view
pages --> data
pages --> refdata
pages --> providers
pages --> infrastructure
pages --> entities
pages --> shared
view --> data
view --> refdata
view --> infrastructure
view --> entities
view --> shared
refdata --> infrastructure
refdata --> shared
providers --> data
providers --> refdata
providers --> infrastructure
providers --> shared
data --> infrastructure
data --> entities
data --> shared
infrastructure --> shared
```
| Layer | Can import from |
| ----------------- | --------------------------------------------------------------------------- |
| `shared/` | nothing — zero app-layer dependencies |
| `entities/` | nothing — zero app-layer dependencies |
| `infrastructure/` | `shared/`, external packages, app runtime config |
| `refdata/` | `infrastructure/`, `shared/` |
| `data/` | `infrastructure/`, `entities/`, `shared/` |
| `providers/` | `infrastructure/`, `data/`, `refdata/`, `shared/` |
| `view/` | `data/`, `refdata/`, `entities/`, `shared/`, generic infrastructure helpers |
| `pages/` | all layers |
### Rules
1. **`shared/` has no imports** — it is infrastructure and UI primitives only. It must not reference any domain type or application layer. If a utility needs a domain type, it does not belong in `shared/`.
2. **`entities/` has no imports** — No logic, no React, no external libraries.
3. **`data/` never imports from `view/` or `pages/`** — data hooks and API functions are completely independent of the UI.
4. **`view/` never imports from `pages/`** — components, forms, and widgets do not depend on page-level composition.
5. **The boundary between `shared/ui/` and `view/components/` is enforced by this rule** — if a component needs to import from `entities/`, it cannot live in `shared/`.
6. **`infrastructure/` contains technical adapters, not feature logic** — HTTP clients, React Query, storage adapters, and formatting service wrappers live here.
7. **`refdata/` contains app-wide lookup data** — country lists, languages, currencies, and other shared backend datasets live here instead of inside one feature module.
### 1. **Entities** Layer
The `entities` layer contains global types and interfaces that define your domain models.
- Define entity types for your business objects: User, Product, Message
- Define enums or constants
- No Framework
- No API or hook logic
### 2. **Data** layer (Data Access Layer)
#### Purpose
The `data` layer is responsible for all interactions with external or internal data sources and state management hooks.
It is the only layer that knows how to fetch, mutate, and map data, while higher layers (`forms`, `widgets`, `pages`) just consume the hooks or data from this layer.
#### Responsibilities
- Handle API calls
- Provide React Query hooks or other state management hooks for data fetching/mutations
- Define DTOs (Data Transfer Objects)
- Provide DTO mappers (map raw API data to app entities or view models)
- Define types/interfaces specific to API responses
- Isolate side-effects like HTTP requests, error handling, or caching
#### Rules and Guidelines
1. Only data and state logic belongs here
- No UI, forms, or layout logic
2. Use React Query (or other state library) for fetching/mutations
- Expose hooks, not raw API functions, to the view layer
3. DTOs + Mappers
- Map API response to internal entities/ types
- Keep external API structure isolated from your app
- Mappers should be covered by unit tests because they define the data-layer contract between API DTOs and app entities
4. Types/Interfaces
- Define API-specific types
- Use entities/ for app-wide types
5. No direct imports from view/ or pages/
- data/ is completely independent
### Infrastructure Layer
The `infrastructure` layer contains app-wide technical adapters.
In the admin app, it lives in `apps/admin/src/infrastructure/`.
Examples:
- configured HTTP clients and interceptors
- React Query helpers, response types, and error normalization
- storage or browser adapters
- app-wide formatting service wrappers such as date and name formatters
This layer should stay feature-agnostic. Feature API modules should use infrastructure clients instead of creating their own clients.
### Reference Data Layer
The `refdata` layer contains app-wide reference datasets.
In the admin app, it lives in `apps/admin/src/refdata/`.
Examples:
- countries
- languages
- currencies
- time zones
- common option dictionaries
Use this layer for backend-backed lookup data shared by multiple modules. If the data belongs to one feature module, keep it in that module's `data/` layer.
### 3. **Providers** layer
The `providers` layer is responsible for global context, app-wide state, and services that need to be available throughout the React application.
It sets up everything that any component or page might need: routing, state management, internationalization, theme, notifications, etc.
### 4. **Pages** layer
- `pages` = the highest-level blocks
- Compose `widgets` + `forms` + `components` + `data` into full pages
- Only page-level layout, routing, and orchestration logic lives here
- Example: `UserPage` → uses `UserProfileWidget` + `UserActivityWidget`
### 5. **View** layer
1. **view/components/**
- “Dumb” components
- Pure UI, no business logic
- Example: `ProductCard`, `UserAvatar`
2. **view/forms/**
- Form components
- Encapsulate form state, validation, and submit logic
- Use hooks from `data/` for mutations/queries
- Example: `CreateProductForm` → uses `useCreateProduct()` from `data/hooks`
3. **view/widgets/**
- Composed components
- Combine `components` + `forms` + `shared/ui`
- Feature blocks that can be reused on multiple pages
- Example: `UserProfileWidget` → contains `UserAvatar`, `UserForm`, `UserStatsTable`
### 6. **Shared** layer
The `shared` layer contains global reusable building blocks for the frontend:
- Components, hooks, utilities, assets, styles
- Not tied to a specific feature or entity
- Can be used by `view`, `pages`, `widgets`, or `forms`
This is where common "Lego" blocks live.
#### Responsibilities
- Provide reusable UI components (`Button`, `Input`, `Modal`, `Card`)
- Provide reusable hooks (`useToggle`, `useDebounce`, `useLocalStorage`)
- Provide utility functions (`formatDate`, `errorHandler`, http helpers)
- Provide assets (icons, images, fonts)
- Provide global styles (CSS variables, global CSS, Tailwind overrides)
#### Rules
- Components here are dumb, reusable, feature-agnostic
- Hooks here are generic, not tied to a single entity or feature
- Assets can be imported anywhere
- Styles are global or utility-level, not component-specific
## Full documentation
- [Entities Layer](./layers/entities.md)
- [Data Layer](./layers/data.md)
- [Infrastructure Layer](./layers/infrastructure.md)
- [Reference Data Layer](./layers/refdata.md)
- [Providers Layer](./layers/providers.md)
- [View Layer](./layers/view.md)
- [Shared Layer](./layers/shared.md)
- [File & Folder Naming Convention](./naming.md)