@hatem427/code-guard-ci 3.6.2 → 3.6.4

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.
@@ -6,107 +6,355 @@
6
6
  export function nextjsGuidelines(): string {
7
7
  return `## Frontend Team Constitution — Next.js (App Router)
8
8
 
9
- ### Principle I. App Router Mandate
9
+ > Version: 1.0.0 | Ratified: 2026-04-03
10
+ > This constitution is the supreme authority for all development decisions. It supersedes personal preferences, external tutorials, and ad-hoc patterns.
10
11
 
11
- - MUST use App Router (\`app/\`).
12
- - Server Components by default.
13
- - Use "use client" ONLY when necessary.
14
- - Prefer Server Actions for mutations.
15
- - Use Route Handlers inside \`app/api/\`.
12
+ ---
13
+
14
+ ### Core Philosophy
15
+
16
+ Build scalable, maintainable, and predictable Next.js systems.
17
+
18
+ **Priority order:** Reusability > Readability > Accessibility > Performance.
19
+
20
+ Every piece of code MUST:
21
+ - Be understandable at first glance
22
+ - Follow a single responsibility
23
+ - Be reusable or explicitly justify why it is not
24
+ - Feel like a well-designed, minimal product API
25
+
26
+ ---
27
+
28
+ ### I. Server-First Architecture
29
+
30
+ - Default to React Server Components (RSC) for ALL components
31
+ - Use Client Components (\`"use client"\`) ONLY when strictly required:
32
+ - User interactivity (\`onClick\`, \`useState\`, \`useEffect\`)
33
+ - Browser-only APIs (\`window\`, \`localStorage\`, \`IntersectionObserver\`)
34
+ - Client Components MUST be placed as deep as possible in the component tree — never wrap large sections unnecessarily
35
+ - Data fetching MUST happen on the server by default
36
+ - Maximize server-rendered HTML; minimize client-side JavaScript
37
+
38
+ ---
39
+
40
+ ### II. Component Design & Reusability
41
+
42
+ - Every component MUST follow the Single Responsibility Principle
43
+ - Every component MUST expose a clean, minimal props API
44
+ - Components MUST be small, focused, and easily composable
45
+ - If a component grows large, it MUST be split into:
46
+ - Sub-components (for UI decomposition)
47
+ - Custom hooks (for logic extraction)
48
+ - Utility functions (for reusable pure logic)
49
+ - Before creating any new component, check for:
50
+ - Existing components in \`/components\`
51
+ - Existing utilities in \`/utils\` or \`/lib\`
52
+ - Existing hooks in \`/hooks\`
53
+ - Shared/reusable components MUST live in \`/components\`
54
+ - No duplicated logic — ever. Extract and reuse
55
+ - No god components (components handling UI + business logic + data fetching simultaneously)
56
+ - Each component MUST feel like a clean, minimal, reusable API:
57
+ \`<Card title="..." description="..." action={<Button />} />\`
58
+
59
+ PROHIBITED:
60
+ - Overloaded props and complex nested internal logic
61
+ - Duplicated logic anywhere in the codebase
62
+
63
+ ---
64
+
65
+ ### III. Design System Enforcement (NON-NEGOTIABLE)
66
+
67
+ \`global.css\` (Tailwind) is the ONLY source of truth for all visual design tokens.
68
+
69
+ The design system MUST define and contain:
70
+ - Colors, Spacing scale, Typography scale
71
+ - Shadows, Blur variants
72
+ - Animation durations and delays
73
+ - Border radii, Breakpoints
16
74
 
17
75
  PROHIBITED:
18
- - Pages Router.
19
- - Unnecessary client components.
20
- - Mixing server/client logic improperly.
76
+ - Inline custom styles (\`style={{}}\`)
77
+ - Arbitrary Tailwind values (\`px-[13px]\`, \`bg-[#ff0000]\`)
78
+ - Using any visual property before adding it as a design token
79
+
80
+ REQUIRED:
81
+ - ✅ Use design tokens ONLY
82
+ - ✅ If a token is missing: add it to \`global.css\` FIRST, then use it
21
83
 
22
84
  ---
23
85
 
24
- ### Principle II. Server vs Client Separation
86
+ ### IV. Accessibility (NON-NEGOTIABLE)
25
87
 
26
- Server Components MUST:
27
- - Fetch data.
28
- - Handle secure logic.
29
- - Access environment variables.
88
+ - Every component MUST use semantic HTML: \`<button>\`, \`<nav>\`, \`<section>\`, \`<article>\`, \`<main>\`, \`<header>\`, \`<footer>\`, \`<aside>\`, \`<form>\`, \`<label>\`
89
+ - Every interactive element MUST include appropriate \`aria-*\` attributes where native semantics are insufficient
90
+ - Every interactive element MUST support full keyboard navigation
91
+ - Focus states MUST be visible and follow the design system
92
+ - Color contrast MUST meet WCAG 2.1 AA minimum (4.5:1 for text, 3:1 for large text/UI)
93
+ - All form inputs MUST have associated \`<label>\` elements
94
+ - Images MUST have meaningful \`alt\` text or \`aria-hidden="true"\` if decorative
95
+ - Dynamic content changes MUST use live regions where appropriate
96
+ - Skip navigation links MUST be provided for page-level layouts
30
97
 
31
- Client Components MUST:
32
- - Handle UI interactivity only.
33
- - Not access server secrets.
98
+ ---
99
+
100
+ ### V. Responsiveness (NON-NEGOTIABLE)
101
+
102
+ - ALL components and layouts MUST be fully responsive
103
+ - Follow mobile-first design: base styles target mobile, use \`sm:\`, \`md:\`, \`lg:\`, \`xl:\`, \`2xl:\` to enhance
104
+ - Every section and page MUST render correctly on:
105
+ - Mobile (320px–767px)
106
+ - Tablet (768px–1023px)
107
+ - Desktop (1024px+)
108
+
109
+ PROHIBITED:
110
+ - ❌ Fixed widths (except for icons and known fixed-size elements)
34
111
 
35
- Never:
36
- - Use \`process.env\` inside client components.
37
- - Perform secure logic in client side.
112
+ REQUIRED:
113
+ - Flexible layouts: \`flex\`, \`grid\`, \`auto\`, \`min/max\`
38
114
 
39
115
  ---
40
116
 
41
- ### Principle III. Data Fetching Strategy
117
+ ### VI. Testing (NON-NEGOTIABLE)
42
118
 
43
- MANDATORY:
44
- - Use async Server Components for data fetching.
45
- - Use Server Actions for mutations.
46
- - Wrap API logic in services.
119
+ - Every component MUST have unit tests covering:
120
+ - Rendering (does it mount without errors)
121
+ - Props behavior (correct response to different props)
122
+ - Edge cases (empty states, missing optional props, boundary values)
123
+ - Accessibility basics (semantic structure, aria attributes)
124
+ - Test file location: colocated in a \`__tests__\` folder next to the component
125
+ - Test file naming: \`ComponentName.test.tsx\`
126
+ - Tests MUST be written alongside the component — no component is complete without tests
127
+
128
+ ---
129
+
130
+ ### VII. Type Safety & Code Quality
131
+
132
+ - TypeScript strict mode MUST be used everywhere
47
133
 
48
134
  PROHIBITED:
49
- - Fetching in random client components.
50
- - Mixing REST calls inside UI.
135
+ - \`any\` type ever
136
+ - \`@ts-ignore\` or \`@ts-expect-error\` without a tracked issue
137
+
138
+ REQUIRED:
139
+ - ✅ Explicit types for: all component props, all API responses, all state shapes, all function parameters/return types, all hook return values
140
+ - ✅ All types MUST live in \`/types\` (shared) or colocated with feature code (feature-specific)
141
+ - ✅ Prefer \`interface\` for object shapes, \`type\` for unions and computed types
51
142
 
52
143
  ---
53
144
 
54
- ### Principle IV. Performance & SEO
145
+ ### VIII. Data Fetching Strategy
55
146
 
56
- MANDATORY:
57
- - Use \`next/image\`.
58
- - Use \`next/link\`.
59
- - Export \`metadata\`.
60
- - Implement \`loading.tsx\` and \`error.tsx\`.
147
+ - Preferred: server-side fetching via React Server Components
148
+ - Use \`fetch\` with appropriate caching (\`force-cache\`, \`no-store\`, \`revalidate\`)
149
+ - Use React \`cache()\` for deduplicating server-side requests
150
+ - Every data-driven component MUST implement:
151
+ - A loading state (skeleton/spinner via \`loading.tsx\` or \`<Suspense>\`)
152
+ - An error state (via \`error.tsx\` or explicit error UI)
61
153
 
62
154
  PROHIBITED:
63
- - Raw \`<img>\`
64
- - Raw \`<a>\` for internal routes
155
+ - Data fetching in Client Components unless strictly required
156
+ - Duplicate API calls — centralize and reuse fetch functions in \`/services\` or \`/lib\`
65
157
 
66
158
  ---
67
159
 
68
- ### Principle V. Folder Architecture
160
+ ### IX. Internationalization (i18n)
161
+
162
+ - The project MUST support multi-language from day one
163
+ - Adding a new language MUST require only adding a new translation file
164
+ - Hybrid translation strategy:
165
+ - Frontend (static): UI labels, buttons, headings, static content from translation files
166
+ - Backend (dynamic): API-driven content served in the requested locale
167
+ - Translation key naming rules:
168
+ - ✅ Semantic and decoupled from content: \`title\`, \`desc\`, \`cta\`, \`item-1\`, \`label\`, \`placeholder\`, \`error-required\`
169
+ - ❌ Keys MUST NOT mirror content: \`welcomeToOurAmazingPlatform\`, \`clickHereToSubmit\`
170
+ - ❌ No hardcoded user-facing text in any component
171
+ - Translation files MUST be organized per-locale: \`/messages/en.json\`, \`/messages/ar.json\`
172
+
173
+ ---
174
+
175
+ ### X. Icon System
176
+
177
+ - ALL icons MUST be rendered through a \`BaseIcon\` component
178
+ - Icon SVG files MUST be stored in \`/assets/icons\`
179
+ - \`BaseIcon\` MUST support: \`name\`, \`size\`, \`className\` props and proper \`aria-hidden\`/\`aria-label\`
180
+
181
+ PROHIBITED:
182
+ - ❌ Direct SVG usage in components
183
+ - ❌ Inline SVG markup in JSX
184
+
185
+ ---
186
+
187
+ ### XI. Performance & Optimization
188
+
189
+ - Minimize client-side JavaScript bundle size
190
+ - Avoid unnecessary re-renders in Client Components
191
+ - Use \`React.memo\` ONLY when profiling confirms a performance issue
192
+ - Use \`next/dynamic\` for lazy-loading heavy Client Components
193
+ - Use \`next/image\` for all images
194
+ - Use \`next/font\` for font loading
195
+ - Prefer CSS-based animations over JavaScript-based animations
196
+ - Code-split at the route level via the App Router
197
+
198
+ ---
199
+
200
+ ### XII. Separation of Concerns
201
+
202
+ | Concern | Location |
203
+ |---------|----------|
204
+ | UI Components | \`/components\` |
205
+ | Logic / Hooks | \`/hooks\` |
206
+ | API Services | \`/services\` |
207
+ | Shared Types | \`/types\` |
208
+ | Utilities | \`/utils\` |
209
+ | Libraries | \`/lib\` |
210
+ | Static Assets | \`/assets\` |
211
+ | Icons | \`/assets/icons\` |
212
+ | Translations | \`/messages\` |
213
+
214
+ PROHIBITED:
215
+ - ❌ Mixing concerns within a single file
216
+ - ❌ Business logic in components
217
+ - ❌ UI rendering in hooks
218
+
219
+ ---
220
+
221
+ ### XIII. Code Cleanliness
222
+
223
+ Naming conventions:
224
+ - Components: \`PascalCase\` (e.g., \`HeroSection\`, \`BaseIcon\`)
225
+ - Hooks: \`camelCase\` with \`use\` prefix (e.g., \`useTranslation\`)
226
+ - Utilities: \`camelCase\` (e.g., \`formatDate\`, \`cn\`)
227
+ - Types/Interfaces: \`PascalCase\` (e.g., \`CardProps\`, \`ApiResponse\`)
228
+ - Constants: \`UPPER_SNAKE_CASE\`
229
+ - Files: \`PascalCase\` for components, \`camelCase\` for utils
230
+
231
+ Comments:
232
+ - ❌ No unnecessary comments — if a comment is needed, the code is too complex; simplify it
233
+ - ✅ Acceptable ONLY for: non-obvious business rules, workarounds with linked issues, JSDoc on exported functions
234
+
235
+ ---
236
+
237
+ ### XIV. Anti-Patterns (STRICTLY FORBIDDEN)
238
+
239
+ - ❌ Large Client Components wrapping server-renderable content
240
+ - ❌ Inline styles (\`style={{}}\`)
241
+ - ❌ Hardcoded user-facing text
242
+ - ❌ Duplicated/repeated logic anywhere in the codebase
243
+ - ❌ Ignoring accessibility requirements
244
+ - ❌ Breaking or bypassing the design system
245
+ - ❌ Using \`any\` type
246
+ - ❌ Unstructured or random folder creation
247
+ - ❌ Over-engineering simple components
248
+ - ❌ Direct SVG usage outside \`BaseIcon\`
249
+ - ❌ Arbitrary Tailwind values
250
+ - ❌ Data fetching in Client Components without justification
251
+ - ❌ Components without unit tests
252
+ - ❌ Hardcoded colors, spacing, or typography values
253
+ - ❌ \`console.log\` in production code
254
+
255
+ ---
256
+
257
+ ### Architecture & Folder Structure
69
258
 
70
259
  \`\`\`
71
- src/
72
- ├── app/ # Routes (Server-first)
73
- ├── components/ # Reusable UI
74
- ├── hooks/ # Custom hooks
75
- ├── services/ # API layer
76
- ├── lib/ # Utilities
77
- └── types/ # Type definitions
260
+ apps/project-name/src/
261
+ ├── app/ # Next.js App Router (routes, layouts, pages, loading, error boundaries)
262
+ ├── [locale]/ # i18n dynamic locale segment
263
+ │ │ ├── layout.tsx
264
+ │ │ ├── page.tsx
265
+ │ │ ├── loading.tsx
266
+ │ │ ├── error.tsx
267
+ │ │ └── [feature]/ # Feature routes
268
+ │ │ ├── page.tsx
269
+ │ │ ├── loading.tsx
270
+ │ │ └── error.tsx
271
+ │ ├── layout.tsx # Root layout
272
+ │ └── global.css # Design system (Tailwind tokens)
273
+ ├── components/
274
+ │ ├── ui/ # Atomic UI components (Button, Input, Card, Badge, Modal, etc.)
275
+ │ ├── shared/ # Shared composed components (Header, Footer, Navbar, BaseIcon, etc.)
276
+ │ └── layout/ # Layout components (Container, Section, Grid, Stack, etc.)
277
+ ├── hooks/ # Custom React hooks
278
+ ├── lib/ # Third-party integrations, config, and framework utilities
279
+ ├── utils/ # Pure utility functions
280
+ ├── services/ # API service layer (fetch wrappers, data transformers)
281
+ ├── types/ # Shared TypeScript type definitions
282
+ ├── assets/
283
+ │ ├── icons/ # SVG icon files (used via BaseIcon)
284
+ │ └── images/ # Static image assets
285
+ └── messages/ # i18n translation files
286
+ ├── en.json
287
+ └── [locale].json
78
288
  \`\`\`
79
289
 
80
- No business logic inside components.
290
+ Rules:
291
+ - No random or ad-hoc folder creation
292
+ - Group by feature within route folders when needed
293
+ - Keep ALL shared logic in global folders (\`/components\`, \`/hooks\`, \`/utils\`, \`/lib\`, \`/services\`, \`/types\`)
294
+ - Feature-specific code lives within its route folder ONLY if it is truly not reusable
81
295
 
82
296
  ---
83
297
 
84
- ### Principle VI. Type & Safety Enforcement
298
+ ### Component Creation Checklist
299
+
300
+ Before any component is marked as complete, verify:
85
301
 
86
- - No \`any\`.
87
- - All route handlers must have try/catch.
88
- - Validate request body.
89
- - Never expose secrets to client.
302
+ - [ ] Is it reusable (or justified why not)?
303
+ - [ ] Does it strictly follow the design system?
304
+ - [ ] Is it fully accessible (semantic HTML, aria, keyboard)?
305
+ - [ ] Is it fully responsive (mobile, tablet, desktop)?
306
+ - [ ] Does it have comprehensive unit tests?
307
+ - [ ] Is it fully typed (no \`any\`, explicit props interface)?
308
+ - [ ] Is it small and focused (single responsibility)?
309
+ - [ ] Does it avoid duplicating existing logic?
310
+ - [ ] Does it use \`BaseIcon\` for any icons?
311
+ - [ ] Does it use translation keys for all user-facing text?
312
+ - [ ] Does it handle loading and error states (if data-driven)?
313
+ - [ ] Is it a Server Component (or justified why client)?
314
+ - [ ] Are new design tokens added to \`global.css\` first?
90
315
 
91
316
  ---
92
317
 
93
- ### Principle VII. Styling & Design
318
+ ### ESLint & Linting Rules
94
319
 
95
- - Follow design tokens.
96
- - Use logical properties for RTL.
97
- - No hardcoded spacing values.
98
- - Prefer Tailwind utility patterns.
320
+ The project MUST enforce the following ESLint rules:
321
+
322
+ \`\`\`
323
+ no-unused-vars: error
324
+ @typescript-eslint/no-explicit-any: error
325
+ @typescript-eslint/consistent-type-imports: warn
326
+ react-hooks/rules-of-hooks: error
327
+ react-hooks/exhaustive-deps: warn
328
+ jsx-a11y/alt-text: error
329
+ jsx-a11y/anchor-is-valid: error
330
+ jsx-a11y/click-events-have-key-events: error
331
+ jsx-a11y/no-static-element-interactions: error
332
+ jsx-a11y/label-has-associated-control: error
333
+ import/order: warn (grouped and alphabetized)
334
+ no-console: warn (error in production builds)
335
+ react/no-unescaped-entities: error
336
+ @next/next/no-img-element: error
337
+ \`\`\`
99
338
 
100
339
  ---
101
340
 
102
- ### Principle VIII. Clean Code & Build Integrity
341
+ ### Governance
103
342
 
104
- PROHIBITED:
105
- - Console logs.
106
- - Dead imports.
107
- - Unused server actions.
108
- - Build warnings.
343
+ **Amendment procedure:**
344
+ 1. Propose a change with rationale and impact assessment
345
+ 2. Document the change in this file with version bump
346
+ 3. Update all dependent templates and artifacts
347
+ 4. Commit with: \`docs: amend constitution to vX.Y.Z (description)\`
109
348
 
110
- Build must pass with \`next build\` without warnings.
349
+ **Versioning policy:**
350
+ - MAJOR: Principle removal, redefinition, or backward-incompatible governance change
351
+ - MINOR: New principle, section, or materially expanded guidance
352
+ - PATCH: Wording clarification, typo fix, non-semantic refinement
353
+
354
+ **Compliance review:**
355
+ - Every PR MUST be checked against this constitution
356
+ - Every new component MUST pass the Component Creation Checklist
357
+ - Violations MUST be fixed before merge — no exceptions
111
358
  `;
112
359
  }
360
+
@@ -33,7 +33,7 @@ console.log(`
33
33
 
34
34
  � Optional — Enable full SBOM scanning (Layer 3):
35
35
 
36
- npm run install-security-tools
36
+ npx code-guard install-security-tools
37
37
 
38
38
  This installs Syft + Grype for deep CVE scanning of your
39
39
  full dependency tree (beyond npm audit and RetireJS).
@@ -464,7 +464,7 @@ function _printGrypeInstallInstructions(): void {
464
464
  }
465
465
 
466
466
  console.log(' │ │');
467
- console.log(' │ Or run: npm run install-security-tools │');
467
+ console.log(' │ Or run: npx code-guard install-security-tools │');
468
468
  console.log(' └─────────────────────────────────────────────────────────────┘');
469
469
  console.log('');
470
470
  }
@@ -62,6 +62,8 @@ export interface DetectionResult {
62
62
  packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun';
63
63
  /** Already-installed tooling */
64
64
  existingTooling: ExistingTooling;
65
+ /** App-level ESLint config paths found in Nx projects (override root config) */
66
+ nxAppEslintConfigs: string[];
65
67
  }
66
68
 
67
69
  // ── Detection logic ─────────────────────────────────────────────────────────
@@ -122,6 +124,48 @@ function detectMonorepo(dir: string, pkg: Record<string, any>): MonorepoType {
122
124
  return 'none';
123
125
  }
124
126
 
127
+ /**
128
+ * Detect app-level ESLint config files in Nx projects.
129
+ * These override the root-level ESLint config.
130
+ */
131
+ function detectNxAppEslintConfigs(dir: string, monorepo: MonorepoType): string[] {
132
+ if (monorepo !== 'nx') return [];
133
+
134
+ const eslintFiles = [
135
+ '.eslintrc', '.eslintrc.js', '.eslintrc.cjs', '.eslintrc.json', '.eslintrc.yml',
136
+ 'eslint.config.js', 'eslint.config.mjs', 'eslint.config.cjs'
137
+ ];
138
+ const found: string[] = [];
139
+
140
+ // Scan apps/ and libs/ directories (standard Nx layout)
141
+ const searchDirs = ['apps', 'libs', 'packages'];
142
+ for (const sub of searchDirs) {
143
+ const subDir = path.join(dir, sub);
144
+ if (!fs.existsSync(subDir) || !fs.statSync(subDir).isDirectory()) continue;
145
+
146
+ let entries: string[];
147
+ try {
148
+ entries = fs.readdirSync(subDir);
149
+ } catch {
150
+ continue;
151
+ }
152
+
153
+ for (const entry of entries) {
154
+ const projectDir = path.join(subDir, entry);
155
+ if (!fs.statSync(projectDir).isDirectory()) continue;
156
+
157
+ for (const eslintFile of eslintFiles) {
158
+ const eslintPath = path.join(projectDir, eslintFile);
159
+ if (fs.existsSync(eslintPath)) {
160
+ found.push(path.relative(dir, eslintPath));
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ return found;
167
+ }
168
+
125
169
  /**
126
170
  * Detect existing tooling already configured in the project.
127
171
  */
@@ -190,6 +234,7 @@ export function detectProject(startDir: string = process.cwd()): DetectionResult
190
234
  hasClaudeConfig: false, hasGeminiConfig: false,
191
235
  hasWindsurfConfig: false, hasJunieConfig: false,
192
236
  },
237
+ nxAppEslintConfigs: [],
193
238
  };
194
239
 
195
240
  if (!result) return defaults;
@@ -200,7 +245,9 @@ export function detectProject(startDir: string = process.cwd()): DetectionResult
200
245
  const usesTypeScript = hasDep(pkg, 'typescript') || fs.existsSync(path.join(dir, 'tsconfig.json'));
201
246
  const existingTooling = detectExistingTooling(dir, pkg);
202
247
 
203
- const base = { rootDir: dir, packageJson: pkg, monorepo, usesTypeScript, packageManager, existingTooling };
248
+ const nxAppEslintConfigs = detectNxAppEslintConfigs(dir, monorepo);
249
+
250
+ const base = { rootDir: dir, packageJson: pkg, monorepo, usesTypeScript, packageManager, existingTooling, nxAppEslintConfigs };
204
251
 
205
252
  // Nuxt check (must come before Vue — Nuxt depends on Vue)
206
253
  if (hasDep(pkg, 'nuxt')) {