--- description: Where to place shared vs module-local code in apps/web (core vs modules) globs: apps/web/src/**/*.{ts,tsx} alwaysApply: false --- # Web Core vs Modules Placement Working directory: `apps/web/`. ## Placement decision | Code kind | Location | |---|---| | Feature / business screen | `src/apps/main/modules///` | | Auth flows | `src/apps/auth/` | | App shell, nav, bookmarks, history | `src/apps/main/layouts/` | | Reusable across **2+ modules** (hook, component, util, store, storage, client) | `src/core/` | | Shared across **apps** (web + showcase + landing + desktop) | `packages/*` (`@repo/ui`, `@repo/core-api`, …) — not `src/core/` | ## `src/core/` structure ```text src/core/ assets/ # App logos, static assets components/ # App-wide UI (e.g. loading-screen) constants/ # App-wide constants / event keys / urls environment/ # ENV config hooks/ # Cross-module hooks (Electron, etc.) lib/ # Singletons (api-client, auth.helper) storage/ # Local / PouchDB adapters stores/ # Cross-module client state (theme, …) ``` ## Hard rules - **Do not** put feature-specific entities, validators, or page UI in `src/core/`. - **Do not** duplicate `apiClient`, storage, or theme logic inside a module — import from `src/core/`. - Module domain factories must use `apiClient` from `src/core/lib/api-client`. - One-module helpers stay under that module’s `domain/` or `presentation/`. - Promote to `src/core/` when a second module needs it; promote to `packages/` when another app needs it. ```typescript // ❌ BAD — module invents its own HTTP client const client = axios.create({ baseURL: '...' }); // ✅ GOOD — shared singleton (same pattern as example/full-page domain factory) import { apiClient } from '../../../../../../../core/lib/api-client'; ```