create-react-scaffold-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/bin/index.js +34 -0
  2. package/package.json +15 -0
  3. package/scripts/createProject.js +30 -0
  4. package/templates/base/.env +1 -0
  5. package/templates/base/.husky/pre-commit +1 -0
  6. package/templates/base/.husky/pre-push +0 -0
  7. package/templates/base/.prettierrc +8 -0
  8. package/templates/base/.vscode/extensions.json +8 -0
  9. package/templates/base/.vscode/settings.json +16 -0
  10. package/templates/base/eslint.config.js +48 -0
  11. package/templates/base/index.html +16 -0
  12. package/templates/base/jsconfig.json +7 -0
  13. package/templates/base/package.json +64 -0
  14. package/templates/base/postcss.config.mjs +7 -0
  15. package/templates/base/readme.md +97 -0
  16. package/templates/base/src/app/App.jsx +13 -0
  17. package/templates/base/src/app/Router.jsx +4 -0
  18. package/templates/base/src/app/app_readme.md +74 -0
  19. package/templates/base/src/app/index.css +1 -0
  20. package/templates/base/src/app/main.jsx +10 -0
  21. package/templates/base/src/app/middlewares/index.js +0 -0
  22. package/templates/base/src/app/providers/QueryProvider.jsx +75 -0
  23. package/templates/base/src/app/providers/index.js +1 -0
  24. package/templates/base/src/features/features_readme.md +102 -0
  25. package/templates/base/src/features/index.js +0 -0
  26. package/templates/base/src/features/sample/components/index.js +0 -0
  27. package/templates/base/src/features/sample/constants/index.js +0 -0
  28. package/templates/base/src/features/sample/constants/sample.constants.js +0 -0
  29. package/templates/base/src/features/sample/hooks/index.js +0 -0
  30. package/templates/base/src/features/sample/pages/index.js +0 -0
  31. package/templates/base/src/features/sample/sample.assets.js +0 -0
  32. package/templates/base/src/features/sample/sample.context.js +0 -0
  33. package/templates/base/src/features/sample/sample.navigations.js +0 -0
  34. package/templates/base/src/features/sample/sample.queryKeys.js +0 -0
  35. package/templates/base/src/features/sample/sample.routes.jsx +0 -0
  36. package/templates/base/src/shared/constants/app.constants.js +4 -0
  37. package/templates/base/src/shared/constants/assets.constants.js +0 -0
  38. package/templates/base/src/shared/constants/index.js +0 -0
  39. package/templates/base/src/shared/contexts/index.js +0 -0
  40. package/templates/base/src/shared/hooks/index.js +3 -0
  41. package/templates/base/src/shared/hooks/useBooleanState.js +19 -0
  42. package/templates/base/src/shared/hooks/useDebounce.js +17 -0
  43. package/templates/base/src/shared/hooks/useToggleState.js +11 -0
  44. package/templates/base/src/shared/layouts/index.js +0 -0
  45. package/templates/base/src/shared/libs/axios.js +6 -0
  46. package/templates/base/src/shared/libs/cn.js +7 -0
  47. package/templates/base/src/shared/libs/index.js +2 -0
  48. package/templates/base/src/shared/shared_readme.md +98 -0
  49. package/templates/base/src/shared/theme/index.js +1 -0
  50. package/templates/base/src/shared/theme/theme.js +2138 -0
  51. package/templates/base/src/shared/ui/Box.jsx +200 -0
  52. package/templates/base/src/shared/ui/Button.jsx +150 -0
  53. package/templates/base/src/shared/ui/Checkbox.jsx +112 -0
  54. package/templates/base/src/shared/ui/DropdownMenu.jsx +152 -0
  55. package/templates/base/src/shared/ui/Flex.jsx +151 -0
  56. package/templates/base/src/shared/ui/FlexItem.jsx +96 -0
  57. package/templates/base/src/shared/ui/FormField.jsx +184 -0
  58. package/templates/base/src/shared/ui/Grid.jsx +151 -0
  59. package/templates/base/src/shared/ui/GridItem.jsx +95 -0
  60. package/templates/base/src/shared/ui/Modal.jsx +43 -0
  61. package/templates/base/src/shared/ui/Scrollable.jsx +47 -0
  62. package/templates/base/src/shared/ui/Select.jsx +207 -0
  63. package/templates/base/src/shared/ui/Sheet.jsx +112 -0
  64. package/templates/base/src/shared/ui/Text.jsx +122 -0
  65. package/templates/base/src/shared/ui/Toaster.jsx +31 -0
  66. package/templates/base/src/shared/ui/index.js +1 -0
  67. package/templates/base/src/shared/utils/getClassName.js +5 -0
  68. package/templates/base/src/shared/utils/index.js +4 -0
  69. package/templates/base/src/shared/utils/memo.js +3 -0
  70. package/templates/base/src/shared/utils/parser.js +41 -0
  71. package/templates/base/src/shared/utils/tryCatch.js +13 -0
  72. package/templates/base/vite.config.js +19 -0
package/bin/index.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+
3
+ import prompts from 'prompts';
4
+ import { createProject } from '../scripts/createProject.js';
5
+
6
+ async function init() {
7
+ const responses = await prompts([
8
+ {
9
+ type: 'text',
10
+ name: 'projectName',
11
+ message: 'What is your project name?',
12
+ validate: (value) => (value ? true : 'Project name is required'),
13
+ },
14
+ {
15
+ type: 'toggle',
16
+ name: 'installDeps',
17
+ message: 'Do you want to install dependencies now?',
18
+ initial: true,
19
+ active: 'yes',
20
+ inactive: 'no',
21
+ },
22
+ ]);
23
+
24
+ const { projectName, installDeps } = responses;
25
+
26
+ if (!projectName) {
27
+ console.log('❌ Project creation cancelled');
28
+ process.exit(1);
29
+ }
30
+
31
+ await createProject(projectName, { installDeps });
32
+ }
33
+
34
+ init();
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "create-react-scaffold-cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "create-react-scaffold": "bin/index.js"
7
+ },
8
+ "dependencies": {
9
+ "commander": "^14.0.2",
10
+ "execa": "^9.6.1",
11
+ "fs-extra": "^11.3.3",
12
+ "prompts": "^2.4.2",
13
+ "react-scaffold": "^0.1.3"
14
+ }
15
+ }
@@ -0,0 +1,30 @@
1
+ import path from 'path';
2
+ import fs from 'fs-extra';
3
+ import { execa } from 'execa';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ export async function createProject(name, options) {
10
+ const { installDeps } = options;
11
+
12
+ const targetDir = path.resolve(process.cwd(), name);
13
+ const templateDir = path.resolve(__dirname, '../templates/base');
14
+
15
+ console.log(`📁 Creating project: ${name}`);
16
+ await fs.copy(templateDir, targetDir);
17
+
18
+ if (installDeps) {
19
+ console.log('📦 Installing dependencies...');
20
+ await execa('npm', ['install'], {
21
+ cwd: targetDir,
22
+ stdio: 'inherit',
23
+ });
24
+ } else {
25
+ console.log('⏭ Skipped dependency installation');
26
+ console.log(`➡ Run 'npm install' inside ${name} when ready`);
27
+ }
28
+
29
+ console.log('✅ Project ready!');
30
+ }
@@ -0,0 +1 @@
1
+ VITE_BACKEND_URL=""
@@ -0,0 +1 @@
1
+ npx lint-staged
Binary file
@@ -0,0 +1,8 @@
1
+ {
2
+ "singleQuote": true,
3
+ "semi": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "plugins": ["prettier-plugin-jsdoc"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "dbaeumer.vscode-eslint",
4
+ "esbenp.prettier-vscode",
5
+ "bradlc.vscode-tailwindcss",
6
+ "dsznajder.es7-react-js-snippets"
7
+ ]
8
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "typescript.updateImportsOnFileMove.enabled": "always",
3
+ "javascript.updateImportsOnFileMove.enabled": "always",
4
+ "editor.formatOnPaste": true,
5
+ "editor.formatOnSave": true,
6
+ "editor.cursorSmoothCaretAnimation": "on",
7
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
8
+ "editor.codeActionsOnSave": {
9
+ "source.fixAll.eslint": "explicit"
10
+ },
11
+ "cSpell.words": ["premiumlogo"],
12
+ "[javascriptreact]": {
13
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
14
+ },
15
+ "liveServer.settings.port": 5501
16
+ }
@@ -0,0 +1,48 @@
1
+ import js from '@eslint/js';
2
+ import react from 'eslint-plugin-react';
3
+ import reactHooks from 'eslint-plugin-react-hooks';
4
+ import reactRefresh from 'eslint-plugin-react-refresh';
5
+ import globals from 'globals';
6
+
7
+ export default [
8
+ js.configs.recommended,
9
+ {
10
+ files: ['**/*.{js,jsx}'],
11
+ languageOptions: {
12
+ ecmaVersion: 2020,
13
+ sourceType: 'module',
14
+ parseOptions: {
15
+ ecmaVersion: {
16
+ jsx: true,
17
+ },
18
+ },
19
+ globals: {
20
+ ...globals.browser,
21
+ window: 'readonly',
22
+ document: 'readonly',
23
+ },
24
+ },
25
+ plugins: {
26
+ react,
27
+ 'react-hooks': reactHooks,
28
+ 'react-refresh': reactRefresh,
29
+ },
30
+ settings: {
31
+ react: {
32
+ version: 'detect',
33
+ },
34
+ },
35
+ rules: {
36
+ 'no-console': 'error',
37
+ 'prefer-const': 'error',
38
+ 'no-fallthrough': 'error',
39
+ 'no-duplicate-imports': 'error',
40
+ 'react/react-in-jsx-scope': 'off',
41
+ 'react/prop-types': 'off',
42
+ 'react-hooks/rules-of-hooks': 'error',
43
+ 'react-hooks/exhaustive-deps': 'warn', // important for hooks
44
+ 'no-undef': 'error', // ⚠ this one detects undefined variables
45
+ 'no-unused-vars': ['warn', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }],
46
+ },
47
+ },
48
+ ];
@@ -0,0 +1,16 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta
7
+ name="viewport"
8
+ content="width=device-width, initial-scale=1, viewport-fit=cover, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
9
+ />
10
+ <title>vite-project</title>
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ <script type="module" src="/src/main.jsx"></script>
15
+ </body>
16
+ </html>
@@ -0,0 +1,7 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "@/*": ["./src/*"]
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "vite-project",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview",
11
+ "prepare": "husky"
12
+ },
13
+ "lint-staged": {
14
+ "src/**/*.{js,jsx}": [
15
+ "eslint --fix",
16
+ "prettier --write"
17
+ ],
18
+ "src/**/*.css": [
19
+ "prettier --write"
20
+ ],
21
+ "package.json": [
22
+ "prettier --write"
23
+ ]
24
+ },
25
+ "dependencies": {
26
+ "@radix-ui/react-dialog": "^1.1.15",
27
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
28
+ "@radix-ui/react-scroll-area": "^1.2.10",
29
+ "@radix-ui/react-select": "^2.2.6",
30
+ "@tailwindcss/postcss": "^4.1.18",
31
+ "@tanstack/react-query": "^5.90.16",
32
+ "@tanstack/react-query-devtools": "^5.91.2",
33
+ "axios": "^1.13.2",
34
+ "clsx": "^2.1.1",
35
+ "nuqs": "^2.8.6",
36
+ "postcss": "^8.5.6",
37
+ "react": "^19.2.0",
38
+ "react-dom": "^19.2.0",
39
+ "react-hot-toast": "^2.6.0",
40
+ "react-icons": "^5.5.0",
41
+ "tailwind-merge": "^3.4.0",
42
+ "tailwindcss": "^4.1.18"
43
+ },
44
+ "devDependencies": {
45
+ "@eslint/js": "^9.39.2",
46
+ "@types/react": "^19.2.5",
47
+ "@types/react-dom": "^19.2.3",
48
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
49
+ "@typescript-eslint/parser": "^8.51.0",
50
+ "@vitejs/plugin-react": "^5.1.1",
51
+ "eslint": "^9.39.2",
52
+ "eslint-config-prettier": "^10.1.8",
53
+ "eslint-plugin-react": "^7.37.5",
54
+ "eslint-plugin-react-hooks": "^7.0.1",
55
+ "eslint-plugin-react-refresh": "^0.4.26",
56
+ "eslint-plugin-unused-imports": "^4.3.0",
57
+ "globals": "^16.5.0",
58
+ "husky": "^9.1.7",
59
+ "lint-staged": "^16.2.7",
60
+ "prettier": "3.7.4",
61
+ "prettier-plugin-jsdoc": "^1.8.0",
62
+ "vite": "^7.2.4"
63
+ }
64
+ }
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1,97 @@
1
+ # React Feature‑First Scaffold
2
+
3
+ ## Purpose
4
+
5
+ This repository is an **internal, opinionated React scaffold** designed for large-scale frontend applications. It enforces a **feature‑first architecture**, clear ownership boundaries, and predictable patterns so teams can scale safely without architectural drift.
6
+
7
+ This scaffold will later be distributed via an internal **NPM CLI** (similar to `create-react-app`) to bootstrap projects with best practices preconfigured.
8
+
9
+ ---
10
+
11
+ ## Core Principles
12
+
13
+ - **Feature-first, not layer-first**
14
+ - **Explicit boundaries** between app / features / shared
15
+ - **Locality of logic** (keep things close to where they are used)
16
+ - **Predictable imports** and naming conventions
17
+ - **Low cognitive load** for new developers
18
+
19
+ ---
20
+
21
+ ## Tech Stack
22
+
23
+ ### Runtime
24
+
25
+ - **React 19** – UI layer
26
+ - **Vite** – fast dev & build tooling
27
+
28
+ ### Styling
29
+
30
+ - **Tailwind CSS** – utility-first styling
31
+ - **tailwind-merge** – class conflict resolution
32
+ - **clsx** – conditional class composition
33
+
34
+ ### Data & State
35
+
36
+ - **@tanstack/react-query** – server-state management
37
+ - **Axios** – HTTP client
38
+
39
+ ### UI Utilities
40
+
41
+ - **Radix UI** – accessible headless components
42
+ - **react-hot-toast** – notifications
43
+ - **react-icons** – icon system
44
+
45
+ ### Code Quality
46
+
47
+ - **ESLint** – linting with strict rules
48
+ - **Prettier** – formatting
49
+ - **Husky + lint-staged** – pre-commit enforcement
50
+
51
+ ---
52
+
53
+ ## High-Level Folder Structure
54
+
55
+ ```txt
56
+ src/
57
+ app/ # Application bootstrap & global wiring
58
+ features/ # Business features (isolated, self-contained)
59
+ shared/ # Cross-feature reusable modules
60
+ ```
61
+
62
+ Each top-level folder has **its own README** explaining rules and responsibilities.
63
+
64
+ ---
65
+
66
+ ## Installation (WIP)
67
+
68
+ > CLI installation instructions will be added once the NPM package is published.
69
+
70
+ For now:
71
+
72
+ ```bash
73
+ npm install
74
+ npm run dev
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Documentation Index
80
+
81
+ - `src/app/README.md` – Application bootstrap & providers
82
+ - `src/features/README.md` – Feature architecture rules
83
+ - `src/shared/README.md` – Shared modules & reuse policy
84
+
85
+ ---
86
+
87
+ ## Philosophy
88
+
89
+ > **Architecture is a product feature.**
90
+
91
+ This scaffold exists to reduce decision fatigue, prevent architectural erosion, and help teams move faster with confidence.
92
+
93
+ ---
94
+
95
+ ## Ownership
96
+
97
+ This scaffold is maintained internally and should be treated as a **living standard**. Changes must be intentional, documented, and agreed upon by the frontend team.
@@ -0,0 +1,13 @@
1
+ import { Toaster } from '@/shared/ui';
2
+ import { QueryProvider } from './providers';
3
+
4
+ function App({ children }) {
5
+ return (
6
+ <QueryProvider>
7
+ {children}
8
+ <Toaster />
9
+ </QueryProvider>
10
+ );
11
+ }
12
+
13
+ export default App;
@@ -0,0 +1,4 @@
1
+
2
+ export const Router = () => {
3
+ return <div className="">{authRoute}</div>;
4
+ };
@@ -0,0 +1,74 @@
1
+ # App Module
2
+
3
+ ## Purpose
4
+ The `app` layer is responsible for **bootstrapping the application**. It wires together global providers, routing, and application-level configuration.
5
+
6
+ This folder should remain **small, boring, and stable**.
7
+
8
+ > If something changes frequently, it probably does NOT belong here.
9
+
10
+ ---
11
+
12
+ ## Responsibilities
13
+
14
+ The `app` module may contain:
15
+
16
+ - Application entry point (`main.jsx`)
17
+ - Root component (`App.jsx`)
18
+ - Global providers (React Query, Theme, etc.)
19
+ - Application router
20
+ - Global middlewares
21
+ - One-time initialization logic
22
+
23
+ ---
24
+
25
+ ## Folder Structure
26
+
27
+ ```txt
28
+ app/
29
+ middlewares/ # Global middlewares (logging, guards, etc.)
30
+ providers/ # Global providers (QueryProvider, ThemeProvider)
31
+ App.jsx # Root component
32
+ Router.jsx # App-level router
33
+ main.jsx # Application entry
34
+ index.css # Global styles
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Rules
40
+
41
+ ### ✅ Allowed
42
+ - Global providers
43
+ - App-wide configuration
44
+ - Router composition
45
+
46
+ ### ❌ Not Allowed
47
+ - Feature-specific logic
48
+ - Business rules
49
+ - UI components
50
+ - API calls
51
+ - Feature contexts
52
+
53
+ ---
54
+
55
+ ## Import Rules
56
+
57
+ ```js
58
+ // ✅ Allowed
59
+ import { QueryProvider } from './providers';
60
+ import { AppRouter } from './Router';
61
+
62
+ // ❌ Not Allowed
63
+ import { LoginForm } from '@/features/auth/components';
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Philosophy
69
+
70
+ The `app` layer is a **composition root**, not a feature owner.
71
+
72
+ Keep it minimal.
73
+ Keep it predictable.
74
+
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -0,0 +1,10 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import App from './App.jsx';
4
+ import './index.css';
5
+
6
+ createRoot(document.getElementById('root')).render(
7
+ <StrictMode>
8
+ <App />
9
+ </StrictMode>
10
+ );
File without changes
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import { MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
+ import { AxiosError } from 'axios';
4
+ import toast from 'react-hot-toast';
5
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
6
+
7
+ export const QueryProvider = ({ children }) => {
8
+ const [queryCache] = React.useState(
9
+ new QueryCache({
10
+ onError: () => {},
11
+ })
12
+ );
13
+
14
+ const [mutationCache] = React.useState(
15
+ new MutationCache({
16
+ onError: (error) => {
17
+ const isAxiosError = error instanceof AxiosError;
18
+
19
+ if (!isAxiosError) {
20
+ return toast.error('Something went wrong.');
21
+ }
22
+ if (error.code === AxiosError.ERR_NETWORK) {
23
+ return toast.error('Network Error');
24
+ }
25
+ if (error.status === 500) {
26
+ return toast.error('Network Error');
27
+ }
28
+ const { response } = error;
29
+ if (!response) {
30
+ return toast.error('Something went wrong');
31
+ }
32
+ const { data } = response;
33
+ if (!data) {
34
+ return toast.error('Something went wrong');
35
+ }
36
+ const { message } = data;
37
+ if (!message) {
38
+ return toast.error('Something went wrong');
39
+ }
40
+ const isIterable = Array.isArray(message);
41
+ if (!isIterable) {
42
+ return toast.error(message);
43
+ }
44
+ for (let index = 0; index < message.length; index++) {
45
+ const error = message[index];
46
+ toast.error(error);
47
+ }
48
+ },
49
+ })
50
+ );
51
+
52
+ const [client] = React.useState(
53
+ new QueryClient({
54
+ queryCache: queryCache,
55
+ mutationCache: mutationCache,
56
+ defaultOptions: {
57
+ queries: {
58
+ retry: false,
59
+ refetchOnWindowFocus: false,
60
+ refetchOnReconnect: false,
61
+ },
62
+ mutations: {
63
+ retry: false,
64
+ },
65
+ },
66
+ })
67
+ );
68
+
69
+ return (
70
+ <QueryClientProvider client={client}>
71
+ {children}
72
+ <ReactQueryDevtools />
73
+ </QueryClientProvider>
74
+ );
75
+ };
@@ -0,0 +1 @@
1
+ export { QueryProvider } from './QueryProvider';
@@ -0,0 +1,102 @@
1
+ # Features Module
2
+
3
+ ## Purpose
4
+
5
+ The `features` folder is the **core of the application**.
6
+
7
+ Each feature represents a **self-contained unit of business functionality** with clear ownership and boundaries.
8
+
9
+ > If a user-facing requirement exists, it belongs to a feature.
10
+
11
+ ---
12
+
13
+ ## Feature-First Architecture
14
+
15
+ Instead of grouping by technical layers (components, hooks, services), we group by **business capability**.
16
+
17
+ This improves:
18
+
19
+ - Scalability
20
+ - Ownership
21
+ - Discoverability
22
+ - Refactor safety
23
+
24
+ ---
25
+
26
+ ## Feature Structure
27
+
28
+ ```txt
29
+ features/<feature-name>/
30
+ assets/ # Feature-specific images/icons
31
+ components/ # Reusable UI within the feature
32
+ constants/ # Feature constants
33
+ hooks/ # Feature-specific hooks
34
+ pages/ # Route-level components
35
+
36
+ <feature>.assets.js
37
+ <feature>.context.js
38
+ <feature>.navigations.js
39
+ <feature>.queryKeys.js
40
+ <feature>.routes.jsx
41
+
42
+ index.js # Public API of the feature
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Rules
48
+
49
+ ### Feature Ownership
50
+
51
+ - A feature **owns its logic, UI, assets, and state**
52
+ - Features should not depend on other features
53
+
54
+ ### Imports
55
+
56
+ ```js
57
+ // ✅ Allowed
58
+ import { Button } from '@/shared/ui';
59
+ import { useAuth } from '@/features/auth';
60
+
61
+ // ❌ Not Allowed
62
+ import { useProfile } from '@/features/profile';
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Constants Policy
68
+
69
+ Feature constants include:
70
+
71
+ - Query keys
72
+ - Navigation definitions
73
+ - Route names
74
+ - Feature-level config
75
+
76
+ > Constants should stay **inside the feature** unless reused across multiple features.
77
+
78
+ ---
79
+
80
+ ## Contexts
81
+
82
+ - Contexts should be **feature-scoped by default**
83
+ - Global contexts require strong justification
84
+
85
+ ---
86
+
87
+ ## Deletion Rule
88
+
89
+ If a feature is removed:
90
+
91
+ - Delete the entire folder
92
+ - No side effects elsewhere
93
+
94
+ If deletion breaks other features, boundaries are violated.
95
+
96
+ ---
97
+
98
+ ## Example Feature
99
+
100
+ `sample/` is a reference feature and can be safely removed.
101
+
102
+ Use it as a blueprint for new features.
File without changes