codeninja 3.2.0 → 4.0.1
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.
- package/README.md +15 -4
- package/agent/database-agent.md +24 -1
- package/agent/nodejs-agent.md +79 -0
- package/cli.js +27 -7
- package/commands/audit.workflow.md +4 -1
- package/commands/db-create-table.workflow.md +1 -1
- package/commands/initialize-project.workflow.md +21 -0
- package/ide/antigravity/.agents/personas/database-architect.md +431 -153
- package/ide/antigravity/.agents/personas/global-orchestrator.md +202 -85
- package/ide/antigravity/.agents/personas/nodejs-backend.md +368 -133
- package/ide/antigravity/.agents/personas/reactjs-frontend.md +182 -101
- package/ide/antigravity/.agents/skills/api-builder/SKILL.md +58 -0
- package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +22 -0
- package/ide/antigravity/.agents/skills/database/SKILL.md +32 -0
- package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +76 -82
- package/ide/antigravity/.agents/skills/reactjs/SKILL.md +36 -0
- package/ide/antigravity/.agents/workflows/codeninja-api.md +76 -83
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +82 -44
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +107 -94
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +89 -67
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +86 -54
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +126 -68
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +87 -59
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +77 -41
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +35 -21
- package/ide/antigravity/.agents/workflows/codeninja-design.md +49 -35
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +41 -20
- package/ide/antigravity/.agents/workflows/codeninja-init.md +479 -289
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +253 -136
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +250 -132
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +71 -29
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +50 -42
- package/ide/antigravity/.agents/workflows/codeninja-review.md +38 -21
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +922 -141
- package/ide/antigravity/.agents/workflows/codeninja-test.md +34 -49
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +449 -151
- package/ide/claude-code/.claude/CLAUDE.md +99 -0
- package/ide/claude-code/.claude/agents/database-agent.md +535 -0
- package/ide/claude-code/.claude/agents/nodejs-agent.md +493 -0
- package/ide/claude-code/.claude/agents/reactjs-agent.md +267 -0
- package/ide/claude-code/.claude/commands/codeninja-api.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-audit.md +119 -0
- package/ide/claude-code/.claude/commands/codeninja-db-create.md +138 -0
- package/ide/claude-code/.claude/commands/codeninja-db-drop.md +109 -0
- package/ide/claude-code/.claude/commands/codeninja-db-index.md +103 -0
- package/ide/claude-code/.claude/commands/codeninja-db-modify.md +165 -0
- package/ide/claude-code/.claude/commands/codeninja-db-seed.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-db-sync.md +106 -0
- package/ide/claude-code/.claude/commands/codeninja-debug.md +99 -0
- package/ide/claude-code/.claude/commands/codeninja-design.md +68 -0
- package/ide/claude-code/.claude/commands/codeninja-explain.md +61 -0
- package/ide/claude-code/.claude/commands/codeninja-init.md +529 -0
- package/ide/claude-code/.claude/commands/codeninja-integrate-api.md +453 -0
- package/ide/claude-code/.claude/commands/codeninja-modularize.md +334 -0
- package/ide/claude-code/.claude/commands/codeninja-optimize.md +129 -0
- package/ide/claude-code/.claude/commands/codeninja-refactor.md +76 -0
- package/ide/claude-code/.claude/commands/codeninja-review.md +87 -0
- package/ide/claude-code/.claude/commands/codeninja-sync.md +964 -0
- package/ide/claude-code/.claude/commands/codeninja-test.md +45 -0
- package/ide/claude-code/.claude/commands/codeninja-validate-page.md +548 -0
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +12 -13
- package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +47 -31
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +32 -110
- package/ide/cursor/.cursor/rules/04-nodejs-generation.mdc +58 -0
- package/ide/cursor/.cursor/rules/05-database.mdc +54 -0
- package/ide/cursor/.cursor/rules/06-reactjs.mdc +36 -0
- package/ide/cursor/.cursor/rules/07-reactjs-generation.mdc +49 -0
- package/ide/cursor/.cursor/rules/08-code-intelligence.mdc +56 -0
- package/ide/cursor/.cursor/rules/09-workflow-steps.mdc +53 -0
- package/ide/vscode/.github/copilot-instructions.md +67 -382
- package/ide/vscode/.vscode/instructions/code-intelligence.instructions.md +58 -0
- package/ide/vscode/.vscode/instructions/database.instructions.md +55 -0
- package/ide/vscode/.vscode/instructions/nodejs.instructions.md +77 -0
- package/ide/vscode/.vscode/instructions/reactjs.instructions.md +42 -0
- package/package.json +2 -2
- package/tasks/ask-hashing-library.task.md +31 -0
- package/tasks/ask-language-type.task.md +26 -0
- package/tasks/ask-new-module-name.task.md +13 -0
- package/tasks/ask-new-service-name.task.md +13 -0
- package/tasks/ask-old-module-name.task.md +15 -0
- package/tasks/ask-old-service-name.task.md +13 -0
- package/tasks/ask-orm-type.task.md +26 -0
- package/tasks/collect-seed-data.task.md +19 -0
- package/tasks/generate-app.task.md +42 -0
- package/tasks/generate-common.task.md +13 -0
- package/tasks/generate-constants.task.md +13 -0
- package/tasks/generate-database.task.md +32 -0
- package/tasks/generate-encryption.task.md +28 -0
- package/tasks/generate-fast-defaults.task.md +7 -0
- package/tasks/generate-hashing.task.md +180 -0
- package/tasks/generate-headerValidator.task.md +13 -0
- package/tasks/generate-ioRedis.task.md +20 -0
- package/tasks/generate-language-en.task.md +12 -0
- package/tasks/generate-logging.task.md +12 -0
- package/tasks/generate-model.task.md +74 -6
- package/tasks/generate-notification.task.md +12 -0
- package/tasks/generate-package-json.task.md +69 -0
- package/tasks/generate-prisma-client.task.md +56 -0
- package/tasks/generate-prisma-schema.task.md +71 -0
- package/tasks/generate-rateLimiter.task.md +20 -0
- package/tasks/generate-readme.task.md +24 -0
- package/tasks/generate-response.task.md +27 -0
- package/tasks/generate-route-manager.task.md +32 -0
- package/tasks/generate-route.task.md +37 -0
- package/tasks/generate-swagger.task.md +8 -0
- package/tasks/generate-template.task.md +12 -0
- package/tasks/generate-tsconfig.task.md +38 -0
- package/tasks/generate-validator.task.md +31 -0
- package/ide/cursor/.cursor/rules/04-database.mdc +0 -90
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +0 -147
- package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +0 -112
|
@@ -1,216 +1,334 @@
|
|
|
1
|
+
This workflow runs when user invokes /codeninja:modularize
|
|
2
|
+
|
|
1
3
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
skills: [mcp-and-context, reactjs, code-intelligence]
|
|
4
|
+
type: workflow
|
|
5
|
+
name: modularize
|
|
5
6
|
description: >
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Scans one or all ReactJS pages, extracts repeated layout blocks
|
|
8
|
+
(header, footer, sidebar, navbar, etc.) into reusable components,
|
|
9
|
+
and rewrites each page to import and use those components. Reuses
|
|
10
|
+
existing components when they already exist. Never rewrites component
|
|
11
|
+
logic — layout structure only.
|
|
9
12
|
---
|
|
10
13
|
|
|
11
|
-
#
|
|
14
|
+
# Workflow: @modularize
|
|
12
15
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
## Goal
|
|
17
|
+
Identify repeated structural blocks across pages, create shared components
|
|
18
|
+
for them under `src/components/`, and update each page to use the new
|
|
19
|
+
components. Result: zero duplicated layout HTML across the project.
|
|
17
20
|
|
|
18
21
|
## Rules
|
|
19
22
|
- Read ALL target pages fully before creating any component
|
|
20
|
-
- NEVER create a component that already exists
|
|
21
|
-
|
|
23
|
+
- NEVER create a component that already exists under `src/components/`
|
|
24
|
+
— reuse it instead
|
|
25
|
+
- NEVER modify business logic, state, API calls, or event handlers
|
|
26
|
+
in any page file — layout structure only
|
|
22
27
|
- NEVER break existing imports or prop flows
|
|
23
28
|
- ONE confirmation before any file is written
|
|
24
|
-
- After writing files →
|
|
29
|
+
- After writing files → run task: `write-context`
|
|
25
30
|
|
|
26
31
|
---
|
|
27
32
|
|
|
28
|
-
##
|
|
33
|
+
## Step-by-Step Execution
|
|
34
|
+
|
|
35
|
+
---
|
|
29
36
|
|
|
30
37
|
### Phase 1 — Target Selection
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
1. Run task: `ask-react-target-service`
|
|
40
|
+
Stores: `context.current_action.service_name`
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- Store: `context.current_action.modularize_scope`
|
|
39
|
-
- If specific → also ask: "Page path?" → Store: `context.current_action.page_path`
|
|
42
|
+
2. Run task: `ask-modularize-scope`
|
|
43
|
+
Stores: `context.current_action.modularize_scope`
|
|
44
|
+
If scope == "specific" → also stores `context.current_action.page_path`
|
|
40
45
|
|
|
41
46
|
---
|
|
42
47
|
|
|
43
48
|
### Phase 2 — Inventory Existing Components
|
|
44
49
|
|
|
45
|
-
Before scanning
|
|
50
|
+
Before scanning pages, inventory what already exists:
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
For each subdirectory → record component name and file path.
|
|
52
|
+
1. Scan `src/components/` in the target service.
|
|
53
|
+
For each subdirectory → record the component name and its file path.
|
|
54
|
+
Example findings:
|
|
55
|
+
- `src/components/Header/index.jsx` → component: Header
|
|
56
|
+
- `src/components/Sidebar/index.jsx` → component: Sidebar
|
|
57
|
+
- `src/components/layout/Navbar/index.jsx` → component: Navbar
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
- Read the file
|
|
52
|
-
- Identify structural role
|
|
53
|
-
|
|
59
|
+
2. For each existing component:
|
|
60
|
+
- Read the file
|
|
61
|
+
- Identify what structural role it plays (header, footer, sidebar,
|
|
62
|
+
navbar, modal wrapper, card shell, breadcrumbs, etc.)
|
|
63
|
+
- Record: `{ name, path, role, props_accepted }`
|
|
54
64
|
|
|
55
|
-
Store
|
|
65
|
+
3. Store the full inventory as the "existing components registry" in memory.
|
|
66
|
+
This is the source of truth for the reuse decision in Phase 4.
|
|
56
67
|
|
|
57
68
|
---
|
|
58
69
|
|
|
59
70
|
### Phase 3 — Scan Target Pages
|
|
60
71
|
|
|
61
72
|
#### If scope == "all":
|
|
62
|
-
Scan `src/pages/` — each subdirectory
|
|
73
|
+
Scan `src/pages/` — for each subdirectory containing `index.jsx` or
|
|
74
|
+
`index.js`, add it to the pages list.
|
|
63
75
|
Also scan `src/views/` if it exists.
|
|
64
76
|
|
|
65
77
|
#### If scope == "specific":
|
|
66
78
|
Pages list = [ context.current_action.page_path ]
|
|
67
79
|
|
|
68
|
-
For each page:
|
|
80
|
+
For each page in the pages list:
|
|
81
|
+
|
|
82
|
+
1. Read the full file content.
|
|
83
|
+
|
|
84
|
+
2. Parse the JSX structure to identify the top-level layout blocks.
|
|
85
|
+
A layout block is a JSX subtree that:
|
|
86
|
+
- Appears at the top level of the return statement (not inside
|
|
87
|
+
a conditional or a list map)
|
|
88
|
+
- Has a clear structural role in the visual layout
|
|
89
|
+
- Does NOT contain unique per-page business logic
|
|
90
|
+
|
|
91
|
+
3. Classify each block using these roles (in priority order):
|
|
92
|
+
- **header** — contains site logo, navigation links, user avatar/menu,
|
|
93
|
+
search bar. Typically rendered at the very top of every page.
|
|
94
|
+
- **footer** — copyright text, footer links, social icons. Bottom.
|
|
95
|
+
- **sidebar** — vertical navigation panel, collapsible menu, drawer.
|
|
96
|
+
- **navbar** — horizontal navigation bar, tab bar, breadcrumbs.
|
|
97
|
+
- **topbar** — page title row with action buttons (e.g. "Users | + Add New")
|
|
98
|
+
- **page-wrapper** — the outer container div that sets max-width,
|
|
99
|
+
padding, or background — wraps all page content.
|
|
100
|
+
- **card** — a bordered/shadowed container used for data display.
|
|
101
|
+
Only extract as a component if it appears in 2+ pages unchanged.
|
|
102
|
+
- **modal-shell** — the backdrop + centered box wrapper for modals.
|
|
103
|
+
Only extract if used in 2+ pages unchanged.
|
|
104
|
+
|
|
105
|
+
4. Record for each block:
|
|
106
|
+
- Role (from list above)
|
|
107
|
+
- Exact JSX tree content
|
|
108
|
+
- Props/variables it references from the parent page scope
|
|
109
|
+
- Which pages it appears in (identical or near-identical)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Phase 4 — Decide: Create vs Reuse vs Skip
|
|
114
|
+
|
|
115
|
+
For each block found across all pages, make one of three decisions:
|
|
69
116
|
|
|
70
|
-
**
|
|
117
|
+
**REUSE** — an existing component from Phase 2 already covers this role.
|
|
118
|
+
Condition: an existing component has the same `role` AND its structure
|
|
119
|
+
matches the block (same element types, same general layout — minor
|
|
120
|
+
class name differences are acceptable).
|
|
121
|
+
Action: the page will import the existing component. No new file created.
|
|
71
122
|
|
|
72
|
-
**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
123
|
+
**CREATE** — no existing component covers this role.
|
|
124
|
+
Condition: no match in existing components registry.
|
|
125
|
+
Additional condition: the block appears in at least ONE page
|
|
126
|
+
(for header/footer/sidebar/navbar/topbar/page-wrapper — always create
|
|
127
|
+
even if seen on only one page, because they are foundational layout).
|
|
128
|
+
For card/modal-shell → only create if seen on 2+ pages unchanged.
|
|
129
|
+
Action: a new component will be created.
|
|
76
130
|
|
|
77
|
-
**
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
131
|
+
**SKIP** — the block is too unique to extract.
|
|
132
|
+
Condition: the block contains page-specific state, API calls, or
|
|
133
|
+
dynamic content that cannot be expressed as simple props.
|
|
134
|
+
Example: a sidebar that renders a different menu depending on user role
|
|
135
|
+
and reads from a page-specific hook → SKIP.
|
|
136
|
+
Action: leave the block inline in the page. Note it in the report.
|
|
81
137
|
|
|
82
138
|
---
|
|
83
139
|
|
|
84
|
-
### Phase
|
|
140
|
+
### Phase 5 — Build Component Plan
|
|
141
|
+
|
|
142
|
+
For each block decided as CREATE, determine:
|
|
85
143
|
|
|
86
|
-
|
|
144
|
+
1. **Component name** — PascalCase of the role.
|
|
145
|
+
Examples: Header, Footer, Sidebar, Navbar, PageTopbar, PageWrapper,
|
|
146
|
+
DataCard, ModalShell.
|
|
147
|
+
If a more specific name is obvious from the content
|
|
148
|
+
(e.g. the sidebar contains "Admin Menu") → use AdminSidebar.
|
|
87
149
|
|
|
88
|
-
**
|
|
89
|
-
|
|
90
|
-
- If a sidebar appears in 2+ pages → one shared Sidebar component
|
|
91
|
-
- If a block appears in only 1 page → do NOT extract it (no duplication benefit)
|
|
150
|
+
2. **File path** — `src/components/<ComponentName>/index.jsx`
|
|
151
|
+
and `src/components/<ComponentName>/<ComponentName>.module.css`
|
|
92
152
|
|
|
93
|
-
**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
153
|
+
3. **Props** — anything the block references from the parent scope
|
|
154
|
+
that varies between pages must become a prop.
|
|
155
|
+
Examples:
|
|
156
|
+
- Page title → `title` prop
|
|
157
|
+
- Active nav item → `activeItem` prop
|
|
158
|
+
- User display name in header → `userName` prop
|
|
159
|
+
Common static content (logo, copyright text, link list) → hardcoded
|
|
160
|
+
inside the component, not a prop.
|
|
161
|
+
|
|
162
|
+
4. **CSS extraction** — any inline styles or style classes that belong
|
|
163
|
+
only to this block are moved to the component's `.module.css` file.
|
|
164
|
+
Classes shared with the rest of the page remain in the page's own
|
|
165
|
+
`.module.css`. Do not break existing page styles.
|
|
97
166
|
|
|
98
167
|
---
|
|
99
168
|
|
|
100
|
-
### Phase
|
|
169
|
+
### Phase 6 — Show Plan and Confirm
|
|
101
170
|
|
|
102
|
-
Display the plan
|
|
171
|
+
Display the modularization plan:
|
|
103
172
|
|
|
104
173
|
```
|
|
105
|
-
|
|
106
|
-
│
|
|
107
|
-
|
|
108
|
-
│ Service
|
|
109
|
-
│
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
│
|
|
113
|
-
│
|
|
114
|
-
│
|
|
115
|
-
│
|
|
116
|
-
│
|
|
117
|
-
│
|
|
118
|
-
│
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
│
|
|
122
|
-
│
|
|
123
|
-
|
|
124
|
-
│
|
|
125
|
-
│ →
|
|
126
|
-
|
|
127
|
-
│
|
|
128
|
-
|
|
174
|
+
┌──────────────────────────────────────────────────────┐
|
|
175
|
+
│ MODULARIZATION PLAN │
|
|
176
|
+
├──────────────────────────────────────────────────────┤
|
|
177
|
+
│ Service : [service_name] │
|
|
178
|
+
│ Pages scanned: [n] │
|
|
179
|
+
├──────────────────────────────────────────────────────┤
|
|
180
|
+
│ COMPONENTS TO CREATE │
|
|
181
|
+
│ → src/components/Header/index.jsx │
|
|
182
|
+
│ Props: userName, activeItem │
|
|
183
|
+
│ Used by: Login, Dashboard, Profile (3 pages) │
|
|
184
|
+
│ │
|
|
185
|
+
│ → src/components/Footer/index.jsx │
|
|
186
|
+
│ Props: none │
|
|
187
|
+
│ Used by: all 3 pages │
|
|
188
|
+
├──────────────────────────────────────────────────────┤
|
|
189
|
+
│ COMPONENTS TO REUSE (already exist) │
|
|
190
|
+
│ → src/components/Sidebar/index.jsx [existing] │
|
|
191
|
+
│ Will be imported into: Dashboard, Profile │
|
|
192
|
+
├──────────────────────────────────────────────────────┤
|
|
193
|
+
│ BLOCKS SKIPPED (too page-specific to extract) │
|
|
194
|
+
│ → Dashboard hero banner — contains dynamic API data │
|
|
195
|
+
├──────────────────────────────────────────────────────┤
|
|
196
|
+
│ PAGES TO UPDATE │
|
|
197
|
+
│ → src/pages/Login/index.jsx │
|
|
198
|
+
│ → src/pages/Dashboard/index.jsx │
|
|
199
|
+
│ → src/pages/Profile/index.jsx │
|
|
200
|
+
└──────────────────────────────────────────────────────┘
|
|
129
201
|
```
|
|
130
202
|
|
|
131
|
-
Ask
|
|
132
|
-
|
|
133
|
-
- If no → abort, nothing written
|
|
134
|
-
- If adjust → ask what to change → re-display plan
|
|
203
|
+
Ask exactly this question:
|
|
204
|
+
"Proceed with this modularization plan? (yes / no / adjust)"
|
|
135
205
|
|
|
136
|
-
|
|
206
|
+
- If yes → proceed to Phase 7 immediately
|
|
207
|
+
- If no → abort. Nothing is created.
|
|
208
|
+
- If adjust → ask: "What would you like to change?"
|
|
209
|
+
Allow the user to exclude a component, rename one, or change a
|
|
210
|
+
prop assignment. Apply the adjustment and re-display the plan.
|
|
137
211
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
For each new component:
|
|
141
|
-
|
|
142
|
-
**Step 1.** Generate `src/components/<ComponentName>/index.jsx`:
|
|
143
|
-
```jsx
|
|
144
|
-
/**
|
|
145
|
-
* <ComponentName> — <one-line description of structural role>.
|
|
146
|
-
*
|
|
147
|
-
* @param {Object} props
|
|
148
|
-
* @param {string} props.<propName> - <description>
|
|
149
|
-
* @returns {JSX.Element}
|
|
150
|
-
*/
|
|
151
|
-
function <ComponentName>({ <props> }) {
|
|
152
|
-
return (
|
|
153
|
-
<extracted JSX block, using props where values varied>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export default <ComponentName>;
|
|
158
|
-
```
|
|
212
|
+
---
|
|
159
213
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
214
|
+
### Phase 7 — Generate Components
|
|
215
|
+
|
|
216
|
+
For each component in the CREATE list:
|
|
217
|
+
|
|
218
|
+
#### Generate `src/components/<ComponentName>/index.jsx`
|
|
219
|
+
|
|
220
|
+
Structure:
|
|
221
|
+
- JSDoc block above the component:
|
|
222
|
+
```
|
|
223
|
+
/**
|
|
224
|
+
* [Role] component shared across all pages.
|
|
225
|
+
*
|
|
226
|
+
* @param {Object} props
|
|
227
|
+
* @param {string} [props.<propName>] - [description] ← one line per prop
|
|
228
|
+
* @returns {JSX.Element}
|
|
229
|
+
*/
|
|
230
|
+
```
|
|
231
|
+
- Import React at the top
|
|
232
|
+
- Import CSS module: `import styles from './<ComponentName>.module.css'`
|
|
233
|
+
- Functional component with props destructured in the signature
|
|
234
|
+
- JSX extracted verbatim from the source page, with parent-scope
|
|
235
|
+
variable references replaced by the corresponding prop name
|
|
236
|
+
- Default export
|
|
237
|
+
|
|
238
|
+
#### Generate `src/components/<ComponentName>/<ComponentName>.module.css`
|
|
239
|
+
|
|
240
|
+
- Move all CSS classes that belong exclusively to this component's
|
|
241
|
+
block from the source page's `.module.css`
|
|
242
|
+
- If no specific classes are used → generate an empty file with a
|
|
243
|
+
comment: `/* Styles for <ComponentName> */`
|
|
164
244
|
|
|
165
245
|
---
|
|
166
246
|
|
|
167
|
-
### Phase
|
|
247
|
+
### Phase 8 — Update Pages
|
|
168
248
|
|
|
169
|
-
For each page that
|
|
249
|
+
For each page in the pages list that references at least one component
|
|
250
|
+
(created or reused):
|
|
170
251
|
|
|
171
|
-
|
|
252
|
+
Read the current page file. Apply these surgical edits:
|
|
172
253
|
|
|
173
|
-
**
|
|
174
|
-
1. Add import at top of file:
|
|
254
|
+
1. **Add imports** at the top of the file, after existing imports:
|
|
175
255
|
```jsx
|
|
176
|
-
import
|
|
256
|
+
import Header from '../../components/Header';
|
|
257
|
+
import Footer from '../../components/Footer';
|
|
177
258
|
```
|
|
178
|
-
|
|
259
|
+
Use the correct relative path from the page file's location to
|
|
260
|
+
`src/components/`. Always use `../../components/` from the standard
|
|
261
|
+
`src/pages/<PageName>/` depth.
|
|
179
262
|
|
|
180
|
-
2. Replace the extracted JSX block with the component
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
263
|
+
2. **Replace the extracted JSX block** with the component tag.
|
|
264
|
+
Pass any required props using the values that were previously
|
|
265
|
+
inline in the page.
|
|
266
|
+
Example:
|
|
267
|
+
Before: `<header className={styles.header}><nav>...</nav></header>`
|
|
268
|
+
After: `<Header activeItem="dashboard" userName={user.name} />`
|
|
269
|
+
|
|
270
|
+
3. **Remove orphaned imports** — if the original block used an import
|
|
271
|
+
that is no longer referenced in the page after extraction
|
|
272
|
+
(e.g. a logo image import that moved into the Header component) →
|
|
273
|
+
remove it from the page's import list.
|
|
184
274
|
|
|
185
|
-
|
|
275
|
+
4. **Clean up orphaned CSS classes** — if classes were moved to the
|
|
276
|
+
component's CSS module, remove them from the page's `.module.css`.
|
|
186
277
|
|
|
187
|
-
|
|
278
|
+
Never modify:
|
|
279
|
+
- Business logic functions (state, useEffect, API calls)
|
|
280
|
+
- The page's own JSX content outside the extracted blocks
|
|
281
|
+
- Event handlers, form logic, any non-layout code
|
|
188
282
|
|
|
189
|
-
**
|
|
283
|
+
> **Multi-agent:** Delegate to `reactjs-frontend` via Task invocation for parallel execution.
|
|
284
|
+
> Read `.codeninja/tasks/` before generating each component and updating pages.
|
|
190
285
|
|
|
191
286
|
---
|
|
192
287
|
|
|
193
|
-
### Phase
|
|
288
|
+
### Phase 9 — Write Context and Report
|
|
194
289
|
|
|
195
|
-
|
|
290
|
+
Run task: `write-context` with:
|
|
196
291
|
- Append to `context.services[<service_name>].components`:
|
|
197
|
-
|
|
292
|
+
For each new component created:
|
|
293
|
+
`{ name, path, role, props, used_by: [page_names], created_by: "modularize" }`
|
|
198
294
|
- Set `last_command` = "modularize"
|
|
199
|
-
- Append to `change_log`:
|
|
295
|
+
- Append to top-level `change_log`:
|
|
296
|
+
`{ timestamp, command: "modularize", action: "Created [n] components, updated [n] pages", affected_files: [...] }`
|
|
297
|
+
- After write-context → call MCP tool `context_clear_scratchpad` with keys: ["current_action"]
|
|
200
298
|
|
|
201
|
-
|
|
299
|
+
Display the modularization report:
|
|
202
300
|
|
|
203
|
-
**Step 3.** Show completion report:
|
|
204
301
|
```
|
|
205
|
-
|
|
302
|
+
@modularize Complete
|
|
206
303
|
─────────────────────────────────────────
|
|
207
304
|
Components created : [n]
|
|
208
305
|
Components reused : [n]
|
|
209
306
|
Pages updated : [n]
|
|
307
|
+
Blocks skipped : [n]
|
|
210
308
|
─────────────────────────────────────────
|
|
211
|
-
|
|
212
|
-
|
|
309
|
+
Created:
|
|
310
|
+
✓ src/components/Header/index.jsx
|
|
311
|
+
✓ src/components/Header/Header.module.css
|
|
312
|
+
✓ src/components/Footer/index.jsx
|
|
313
|
+
✓ src/components/Footer/Footer.module.css
|
|
314
|
+
|
|
315
|
+
Updated:
|
|
316
|
+
✓ src/pages/Login/index.jsx
|
|
317
|
+
✓ src/pages/Dashboard/index.jsx
|
|
318
|
+
✓ src/pages/Profile/index.jsx
|
|
213
319
|
─────────────────────────────────────────
|
|
214
|
-
Next: /codeninja:validate-page to add validation
|
|
215
|
-
/codeninja:integrate-api to wire forms to backend
|
|
216
320
|
```
|
|
321
|
+
|
|
322
|
+
Run task: `show-final-summary`
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## What This Workflow Does NOT Do
|
|
327
|
+
|
|
328
|
+
- Does not create page-level components (forms, tables, charts) —
|
|
329
|
+
only layout/structural shell components
|
|
330
|
+
- Does not add routing — components are not registered in App.jsx
|
|
331
|
+
- Does not touch any backend files
|
|
332
|
+
- Does not modify apiHandler.js or apiClient.js
|
|
333
|
+
- Does not add state management (Redux, Context API)
|
|
334
|
+
- Does not install any new npm packages
|
|
@@ -1,17 +1,30 @@
|
|
|
1
|
+
This workflow runs when user invokes /codeninja:optimize
|
|
2
|
+
|
|
1
3
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type: workflow
|
|
5
|
+
name: optimize
|
|
6
|
+
description: >
|
|
7
|
+
Analyse and improve performance of a route, query, or service using real
|
|
8
|
+
project context — actual table sizes, existing indexes, query patterns, and
|
|
9
|
+
middleware overhead. Produces ranked recommendations with concrete code.
|
|
6
10
|
---
|
|
7
11
|
|
|
8
|
-
# /codeninja:optimize
|
|
12
|
+
# Workflow: @optimize / /codeninja:optimize
|
|
9
13
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
## Goal
|
|
15
|
+
Find real performance bottlenecks using actual project data. Every
|
|
16
|
+
recommendation includes a concrete fix and an estimated impact.
|
|
17
|
+
No generic advice — only changes grounded in this codebase.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
- Check context.db.schema for existing indexes before recommending new ones
|
|
21
|
+
- Reference real table names and column names from context
|
|
22
|
+
- Estimate impact where possible (e.g., "seq scan → index scan on 2M rows")
|
|
23
|
+
- Rank by impact: HIGH → MED → LOW
|
|
24
|
+
|
|
25
|
+
---
|
|
13
26
|
|
|
14
|
-
##
|
|
27
|
+
## Step-by-Step Execution
|
|
15
28
|
|
|
16
29
|
### Step 1 — Identify Target
|
|
17
30
|
If not specified, ask:
|
|
@@ -22,8 +35,9 @@ If not specified, ask:
|
|
|
22
35
|
(d) Something else — describe it"
|
|
23
36
|
|
|
24
37
|
### Step 2 — Load Context
|
|
25
|
-
1. Call `
|
|
26
|
-
2.
|
|
38
|
+
1. Call `context_read` — load `context.db.schema`, `context.services`
|
|
39
|
+
2. Call `fs_read` on the relevant files (route.js, _model.js)
|
|
40
|
+
3. For DB queries: list existing indexes from `context.db.schema.<table>.indexes`
|
|
27
41
|
|
|
28
42
|
### Step 3A — Database Query Analysis
|
|
29
43
|
|
|
@@ -31,54 +45,82 @@ For each query in the target:
|
|
|
31
45
|
|
|
32
46
|
**Check 1 — Missing Indexes**
|
|
33
47
|
Compare WHERE / JOIN / ORDER BY columns against existing indexes.
|
|
34
|
-
|
|
48
|
+
```
|
|
49
|
+
Table: tbl_scores
|
|
50
|
+
Query: WHERE week_id = $1 ORDER BY score DESC
|
|
51
|
+
Indexes on tbl_scores: [id, user_id] ← week_id NOT indexed
|
|
52
|
+
Fix: CREATE INDEX CONCURRENTLY idx_scores_week_id_score
|
|
53
|
+
ON tbl_scores(week_id, score DESC);
|
|
54
|
+
Impact: HIGH — seq scan on every leaderboard call → index scan
|
|
55
|
+
```
|
|
35
56
|
|
|
36
57
|
**Check 2 — SELECT * Anti-Pattern**
|
|
37
|
-
|
|
58
|
+
```
|
|
59
|
+
Before: SELECT * FROM tbl_users WHERE user_id = $1
|
|
60
|
+
After: SELECT id, user_id, display_name, status FROM tbl_users WHERE user_id = $1
|
|
61
|
+
Why: Eliminates unused column transfer; avoids fetching large text/jsonb columns
|
|
62
|
+
```
|
|
38
63
|
|
|
39
64
|
**Check 3 — N+1 Query Pattern**
|
|
40
|
-
Flag any loop
|
|
65
|
+
Flag any loop that calls a DB function per iteration.
|
|
66
|
+
Suggest: single query with IN clause or JOIN.
|
|
41
67
|
|
|
42
68
|
**Check 4 — Window Function Choice**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
69
|
+
```
|
|
70
|
+
RANK() → gaps after ties (positions: 1, 2, 2, 4) ← usually wrong for leaderboards
|
|
71
|
+
DENSE_RANK() → no gaps (positions: 1, 2, 2, 3) ← correct for leaderboards
|
|
72
|
+
ROW_NUMBER() → unique position per row (1, 2, 3, 4) ← correct for pagination
|
|
73
|
+
```
|
|
46
74
|
|
|
47
75
|
**Check 5 — Duplicate Row Prevention**
|
|
48
|
-
|
|
76
|
+
```
|
|
77
|
+
-- Symptom: same user appears multiple times in results
|
|
78
|
+
-- Fix: dedup using MIN(id) GROUP BY user_id before joining
|
|
79
|
+
SELECT MIN(id) as id, user_id FROM tbl_users GROUP BY user_id
|
|
80
|
+
```
|
|
49
81
|
|
|
50
82
|
**Check 6 — Functional Index Trap**
|
|
51
|
-
|
|
83
|
+
```
|
|
84
|
+
-- BAD: DATE(created_at) = '2026-04-13' prevents index use
|
|
85
|
+
-- GOOD: created_at >= '2026-04-13' AND created_at < '2026-04-14'
|
|
86
|
+
```
|
|
52
87
|
|
|
53
88
|
**Check 7 — work_mem for Sort Operations**
|
|
54
|
-
If EXPLAIN shows external merge
|
|
89
|
+
If EXPLAIN shows "Sort Method: external merge Disk:", recommend:
|
|
90
|
+
```sql
|
|
91
|
+
SET work_mem = '64MB'; -- session-level, before the heavy query
|
|
92
|
+
```
|
|
55
93
|
|
|
56
94
|
### Step 3B — API Route Analysis
|
|
57
95
|
|
|
58
|
-
|
|
59
|
-
-
|
|
96
|
+
Check middleware chain for overhead:
|
|
97
|
+
- Is heavy middleware applied to lightweight routes?
|
|
98
|
+
- Any synchronous blocking in the request path?
|
|
60
99
|
- Repeated DB lookups that could be cached in Redis?
|
|
61
|
-
|
|
100
|
+
|
|
101
|
+
Check response size:
|
|
102
|
+
- Is pagination applied to list endpoints?
|
|
103
|
+
- Any large JSON blobs being serialized unnecessarily?
|
|
62
104
|
|
|
63
105
|
### Step 4 — Output Recommendations
|
|
64
106
|
|
|
65
107
|
```
|
|
66
108
|
[HIGH | MED | LOW] — Impact label
|
|
67
109
|
|
|
68
|
-
Target: what's being optimised
|
|
110
|
+
Target: describe what's being optimised
|
|
69
111
|
Root cause: why it's slow right now
|
|
70
112
|
Fix:
|
|
71
113
|
[exact SQL or code change]
|
|
72
114
|
Estimated gain: concrete estimate
|
|
73
|
-
Side effects: anything developer should know
|
|
115
|
+
Side effects: anything the developer should know
|
|
74
116
|
```
|
|
75
117
|
|
|
76
|
-
List all, highest impact first.
|
|
118
|
+
List all recommendations, highest impact first.
|
|
77
119
|
|
|
78
120
|
### Step 5 — Offer to Apply
|
|
79
121
|
"I've found [N] optimisations. Want me to apply them?
|
|
80
122
|
I'll implement each one and show you the change before writing."
|
|
81
123
|
|
|
82
|
-
For index changes
|
|
83
|
-
For code changes
|
|
84
|
-
Always call `context_write` after applying index additions.
|
|
124
|
+
For index changes: generate `NNN_add_index_<name>.sql` migration file.
|
|
125
|
+
For code changes: edit the relevant model or route file surgically.
|
|
126
|
+
Always call `context_write` after applying index additions to update schema.
|