codeninja 3.1.0 → 3.2.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.
- package/ide/antigravity/.agents/personas/global-orchestrator.md +103 -84
- package/ide/antigravity/.agents/workflows/codeninja-api.md +98 -15
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +69 -11
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +118 -5
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +81 -5
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +64 -5
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +100 -5
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +70 -4
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +64 -6
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +76 -6
- package/ide/antigravity/.agents/workflows/codeninja-design.md +45 -12
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +35 -6
- package/ide/antigravity/.agents/workflows/codeninja-init.md +329 -22
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +334 -9
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +214 -9
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +78 -7
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +58 -13
- package/ide/antigravity/.agents/workflows/codeninja-review.md +64 -6
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +172 -12
- package/ide/antigravity/.agents/workflows/codeninja-test.md +51 -9
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +248 -9
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +35 -32
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +100 -50
- package/ide/cursor/.cursor/rules/04-database.mdc +73 -70
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +133 -69
- package/ide/vscode/.github/copilot-instructions.md +304 -190
- package/package.json +1 -1
|
@@ -1,87 +1,90 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: codeninja
|
|
2
|
+
description: codeninja Database Architect — table design, migrations, indexes, seeds
|
|
3
3
|
globs: ["**/database/**", "**/*.sql", "**/migrations/**"]
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# codeninja — Database Architect
|
|
8
8
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
## Critical Rule
|
|
10
|
+
`database/` folder is ALWAYS at the repository root — NEVER inside a service folder.
|
|
11
|
+
All services share the same database directory.
|
|
12
12
|
|
|
13
|
-
##
|
|
14
|
-
| Element | Rule | Example |
|
|
15
|
-
|---------|------|---------|
|
|
16
|
-
| Table | `tbl_` prefix, lowercase, plural | `tbl_users` |
|
|
17
|
-
| Column | lowercase snake_case | `user_id`, `created_at` |
|
|
18
|
-
| PK | `id` bigint identity, first | always |
|
|
19
|
-
| FK | `<table_singular_no_prefix>_id` | `user_id` → `tbl_users` |
|
|
20
|
-
| Index (per-table) | `idx_<table_no_prefix>_<cols>` | `idx_users_email` |
|
|
21
|
-
| Index (global) | `idx_tbl_<table>_<cols>` | `idx_tbl_users_email_is_deleted` |
|
|
22
|
-
| Create file | `<N>-setup-tbl-<n>.sql` | `3-setup-tbl-users.sql` |
|
|
23
|
-
| Alter file | `<N>-alter-tbl-<n>-<desc>.sql` | `12-alter-tbl-users-add-kyc.sql` |
|
|
24
|
-
| Drop file | `<N>-drop-tbl-<n>.sql` | `13-drop-tbl-sessions.sql` |
|
|
25
|
-
| Shared indexes | `111-setup-database-indexes.sql` | always last |
|
|
13
|
+
## /codeninja:db:create — New Table
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
15
|
+
1. Ask: table purpose (used for column suggestions)
|
|
16
|
+
2. Ask: table name (must start with `tbl_`, snake_case, lowercase)
|
|
17
|
+
3. Ask: migration file number (agent reads migrations/ and suggests next via `migration_next_number`)
|
|
18
|
+
4. Ask: needs `status` + `is_deleted` columns? (suggest YES for entity tables, NO for log tables)
|
|
19
|
+
5. Ask: needs soft delete `is_deleted`? (auto-suggest YES if needs_status)
|
|
20
|
+
6. Column collection loop (repeat until "done"):
|
|
21
|
+
- Ask column name (snake_case) + type (show suggestion by name pattern):
|
|
22
|
+
- `*_id` → BIGINT NOT NULL DEFAULT 0 (also check FK — ask if references another table)
|
|
23
|
+
- `is_*` → BOOLEAN NOT NULL DEFAULT FALSE
|
|
24
|
+
- `*_at` → TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
25
|
+
- `status` → INTEGER NOT NULL DEFAULT 0 CHECK (status IN (0,1))
|
|
26
|
+
- `email` → VARCHAR(132) NOT NULL DEFAULT ''
|
|
27
|
+
- `phone` → VARCHAR(16) NOT NULL DEFAULT ''
|
|
28
|
+
- `password` → TEXT NOT NULL DEFAULT ''
|
|
29
|
+
- `*_image`, `*_url` → VARCHAR(255) NOT NULL DEFAULT ''
|
|
30
|
+
- `payload`, `metadata` → JSON NOT NULL DEFAULT '{}'
|
|
31
|
+
- Ask: is this an enum column? If yes → collect allowed values → CHECK constraint + COMMENT
|
|
32
|
+
7. Index suggestions: auto-suggest for every FK column, status+is_deleted compound, created_at DESC for logs
|
|
33
|
+
8. Ask: seed data needed? (YES only for reference/master tables)
|
|
34
|
+
9. Show complete table summary — ask: "Generate? (yes / no / change)"
|
|
35
|
+
10. Generate migration file at `database/<db_type>/migrations/<n>-setup-tbl-<name>.sql`
|
|
36
|
+
11. Update `create-schema.sql` with `\i` entry in numeric order
|
|
37
|
+
12. Call `context_write` — append to context.db.schema.tables and change_log
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
## /codeninja:db:modify — Alter Table
|
|
40
|
+
- Always generate an ALTER file — NEVER edit the original setup file
|
|
41
|
+
- Operations: add column, rename column, drop column, change type, add CHECK constraint, add index
|
|
42
|
+
- For "add index" → route to /codeninja:db:index instead
|
|
43
|
+
- Generated file: `<n>-alter-tbl-<name>-<description>.sql`
|
|
44
|
+
- Wrap in `BEGIN; ... COMMIT;`
|
|
49
45
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
4. COMMENT ON COLUMN for every enum/flag column
|
|
56
|
-
5. Per-table CREATE INDEX statements
|
|
57
|
-
6. ALTER TABLE public.<table> OWNER TO <context.db.user>;
|
|
58
|
-
7. GRANT ALL ON TABLE public.<table> TO <context.db.user>;
|
|
59
|
-
8. INSERT seed data (reference tables only)
|
|
60
|
-
```
|
|
46
|
+
## /codeninja:db:index — Add Index
|
|
47
|
+
- Ask: table, column(s), sort order (DESC?), standard vs partial (WHERE clause?)
|
|
48
|
+
- Ask: table's own file vs `111-setup-database-indexes.sql` (auto-suggest shared file for existing tables)
|
|
49
|
+
- Index naming: `idx_<table_without_tbl_prefix>_<columns>` (table file) or `idx_tbl_<name>_<columns>` (shared)
|
|
50
|
+
- Always show generated name and confirm before writing
|
|
61
51
|
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
52
|
+
## /codeninja:db:drop — Drop Table
|
|
53
|
+
- NEVER delete original setup file — generate new drop migration
|
|
54
|
+
- Show impact analysis: routes referencing table, FK dependencies
|
|
55
|
+
- Require user to type table name exactly to confirm
|
|
56
|
+
- Generated file: `<n>-drop-tbl-<name>.sql` with `DROP TABLE IF EXISTS ... CASCADE`
|
|
57
|
+
- Keep original `\i <setup_file>` in create-schema.sql — add drop file AFTER it
|
|
58
|
+
- Save full column snapshot to change_log before removing from active tables
|
|
69
59
|
|
|
70
|
-
##
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
- Any WHERE or ORDER BY column in business queries
|
|
60
|
+
## /codeninja:db:seed — Add Seed Data
|
|
61
|
+
- Determine: append to setup file (reference/master data) OR standalone seeds/ file (dev data)
|
|
62
|
+
- NEVER store plaintext passwords — warn user to provide encrypted value
|
|
63
|
+
- Multi-row INSERT only (single INSERT with multiple value tuples)
|
|
64
|
+
- File: `database/<db_type>/seeds/<table_name>_seed.sql`
|
|
76
65
|
|
|
77
|
-
##
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
66
|
+
## /codeninja:db:sync — Rebuild Schema from Files
|
|
67
|
+
- Parse all migration files in numeric order: setup → alter → drop → indexes
|
|
68
|
+
- Rebuild context.db.schema from actual file contents
|
|
69
|
+
- Rewrite create-schema.sql to match actual files on disk
|
|
70
|
+
- Report stale entries (in create-schema.sql but not on disk) and missing entries
|
|
81
71
|
|
|
82
|
-
##
|
|
72
|
+
## SQL Standards
|
|
83
73
|
```sql
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
-- Standard table structure
|
|
75
|
+
CREATE TABLE public.tbl_<name> (
|
|
76
|
+
id BIGSERIAL PRIMARY KEY,
|
|
77
|
+
-- ... columns ...
|
|
78
|
+
status INTEGER NOT NULL DEFAULT 0 CHECK (status IN (0,1)),
|
|
79
|
+
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
80
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
COMMENT ON COLUMN public.tbl_<name>.<col> IS 'Values: 0=<label>, 1=<label>';
|
|
84
|
+
|
|
85
|
+
CREATE INDEX idx_<name>_<col> ON public.tbl_<name> (<col>);
|
|
86
|
+
|
|
87
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.tbl_<name> TO <db_user>;
|
|
86
88
|
```
|
|
87
|
-
|
|
89
|
+
|
|
90
|
+
All ALTER and DROP migrations wrapped in `BEGIN; ... COMMIT;`.
|
|
@@ -1,83 +1,147 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: codeninja ReactJS
|
|
3
|
-
globs: ["**/src
|
|
2
|
+
description: codeninja ReactJS Frontend — scaffolding, modularize, validate-page, integrate-api
|
|
3
|
+
globs: ["**/src/**/*.jsx", "**/src/**/*.js", "**/public/**", "**/.htaccess"]
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# codeninja — ReactJS Frontend
|
|
8
8
|
|
|
9
|
-
## Backend Linking (enforced
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
## Backend Linking Rule (enforced)
|
|
10
|
+
ReactJS service CANNOT initialize without a linked NodeJS service.
|
|
11
|
+
Security values (KEY, IV, API_KEY) are ALWAYS inherited from the linked backend — never asked from user.
|
|
12
|
+
|
|
13
|
+
## /codeninja:init — ReactJS App Scaffolding
|
|
14
|
+
|
|
15
|
+
### Phase 1 — Linking
|
|
16
|
+
- List available NodeJS services from context.services
|
|
17
|
+
- Ask: which NodeJS service to link to?
|
|
18
|
+
- Auto-inherit: encryption_key, encryption_iv, api_key from linked service
|
|
19
|
+
- Ask: service name, description
|
|
20
|
+
|
|
21
|
+
### Phase 2 — Single Confirmation, Then Generate ALL Files
|
|
22
|
+
|
|
23
|
+
**Wave 1:** package.json, .env (inherited values), .env.example, .gitignore, README.md,
|
|
24
|
+
public/index.html, public/assets/css/style.css (empty reset), public/robots.txt,
|
|
25
|
+
public/favicon.ico (placeholder), .htaccess (root), public/.htaccess
|
|
26
|
+
|
|
27
|
+
**Wave 2:** src/api/apiClient.js, src/api/apiHandler.js
|
|
28
|
+
|
|
29
|
+
**Wave 3:** src/pages/Welcome/index.jsx, src/pages/Welcome/Welcome.module.css,
|
|
30
|
+
src/App.jsx, src/index.jsx, src/components/.gitkeep
|
|
31
|
+
|
|
32
|
+
**Wave 4:** Dockerfile, nginx.conf, .dockerignore
|
|
33
|
+
|
|
34
|
+
Completion gate — verify before proceeding:
|
|
35
|
+
- public/index.html, src/api/apiClient.js, src/api/apiHandler.js, src/App.jsx, src/index.jsx, .env
|
|
36
|
+
|
|
37
|
+
### apiClient.js — 4 Responsibilities
|
|
38
|
+
1. Static headers: `api-key` (from REACT_APP_API_KEY), `Accept-Language`, `Content-Type: text/plain`
|
|
39
|
+
2. Request interceptor: encrypt body; attach AES-encrypted `token` from localStorage (`wa_token`) if present
|
|
40
|
+
3. Response interceptor (success): decrypt body; parse JSON; code -1 → logout redirect
|
|
41
|
+
4. Response interceptor (error): ERR_NETWORK / 401 → logout redirect + error message
|
|
42
|
+
|
|
43
|
+
### apiHandler.js Standard
|
|
44
|
+
- One async function per API endpoint
|
|
45
|
+
- Each calls `axiosClient.post/get/put/patch/delete(path, payload)` and returns directly
|
|
46
|
+
- No try/catch, no decryption, no response shaping in this file
|
|
47
|
+
- Only place in frontend where API endpoint paths are written
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## /codeninja:modularize — Extract Layout Components
|
|
52
|
+
|
|
53
|
+
**Rule:** Layout structure only — NEVER touch business logic, state, API calls, event handlers.
|
|
54
|
+
NEVER create a component that already exists — reuse it.
|
|
55
|
+
|
|
56
|
+
1. Ask: which ReactJS service
|
|
57
|
+
2. Ask: all pages OR specific page
|
|
58
|
+
3. Inventory existing `src/components/` — record name, path, structural role, props
|
|
59
|
+
4. Scan target pages — identify repeated layout blocks (header, nav, footer, sidebar, etc.)
|
|
60
|
+
5. Cross-check: if block matches existing component → mark "reuse", else "new component needed"
|
|
61
|
+
6. Group blocks by similarity across pages — only extract if appears in 2+ pages
|
|
62
|
+
7. Show extraction plan with component names, props, files to create, pages to update
|
|
63
|
+
8. Ask: "Apply? (yes / no / adjust)"
|
|
64
|
+
9. Generate each new component:
|
|
65
|
+
- `src/components/<ComponentName>/index.jsx` — props for varying values
|
|
66
|
+
- `src/components/<ComponentName>/<ComponentName>.module.css`
|
|
67
|
+
10. Update each page: add import, replace extracted JSX with `<ComponentName prop={value} />`,
|
|
68
|
+
remove now-unused imports, remove moved CSS classes
|
|
69
|
+
11. Call `context_write` — append to context.services[<n>].components
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## /codeninja:validate-page — Add Form Validation
|
|
74
|
+
|
|
75
|
+
**Rule:** ONE page per run. NEVER modify API calls or business logic. NEVER overwrite existing validation.
|
|
76
|
+
|
|
77
|
+
1. Ask: which ReactJS service, which page path
|
|
78
|
+
2. Ask: validation library (Yup | React Hook Form | Parsley | Validator.js | Custom)
|
|
79
|
+
3. Scan page: find all `<form>`, `<input>`, `<select>`, `<textarea>`, `<button type="submit">`
|
|
80
|
+
4. For each field: record type, name, id, placeholder, label text, existing validation
|
|
81
|
+
5. Detect existing validation patterns — skip already-validated fields
|
|
82
|
+
6. Infer semantic type from label/name/placeholder → assign standard error messages:
|
|
83
|
+
- email: "Please enter a valid email address."
|
|
84
|
+
- password: "Password must be at least 8 characters."
|
|
85
|
+
- confirmPassword: "Password and confirm password do not match."
|
|
86
|
+
- phone: "Please enter a valid phone number."
|
|
87
|
+
- required generic: "This field is required."
|
|
88
|
+
7. Assign missing `name` and `id` attributes (camelCase from label text)
|
|
89
|
+
8. Show validation plan — ask: "Apply? (yes / no / adjust)"
|
|
90
|
+
9. Apply by library:
|
|
91
|
+
- **Yup:** validationSchema above component, validateForm async function, `{errors.field && <span>...}`
|
|
92
|
+
- **RHF:** useForm hook, `{...register('field', rules)}`, `{errors.field && <span>...}`
|
|
93
|
+
- **Parsley:** CDN scripts in index.html, data-parsley-* attributes, useEffect init
|
|
94
|
+
- **Validator.js:** import validator, validateForm function with validator.isEmail() etc.
|
|
95
|
+
- **Custom:** plain JS validateForm — no imports
|
|
96
|
+
10. Add `.errorMsg` class to page's `.module.css`
|
|
97
|
+
11. Add package to package.json if needed (yup/react-hook-form/validator)
|
|
98
|
+
12. Call `context_write` — append to context.services[<n>].validated_pages
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## /codeninja:integrate-api — Wire Forms to Backend
|
|
103
|
+
|
|
104
|
+
**Rule:** ONE page per run. NEVER modify layout, CSS, or validation. ALWAYS use apiHandler.js.
|
|
105
|
+
|
|
106
|
+
1. Ask: which ReactJS service, which page path
|
|
107
|
+
2. Ask: all forms/buttons OR specific form/button
|
|
108
|
+
3. Load: linked backend service, context.api_routes for that backend, page content, apiHandler.js
|
|
109
|
+
4. Scan page: identify all forms, action buttons, existing API calls
|
|
110
|
+
5. For each integration point, determine match type:
|
|
111
|
+
- existing handler → use as-is
|
|
112
|
+
- matching route in context.api_routes → add new handler to apiHandler.js
|
|
113
|
+
- no route exists → add TODO placeholder
|
|
114
|
+
6. Design state requirements (loading, error, data states) per form
|
|
115
|
+
7. Show integration plan with handler names, routes, match types, files to modify
|
|
116
|
+
8. Ask: "Apply? (yes / no / adjust)"
|
|
117
|
+
9. Apply:
|
|
118
|
+
- Append new functions to apiHandler.js (for new_handler and no_route matches)
|
|
119
|
+
- Add imports, state declarations, handler functions to page file (surgically — never rewrite)
|
|
120
|
+
- Wire form onSubmit / button onClick
|
|
121
|
+
- Add `disabled={loading}` and conditional button text
|
|
122
|
+
- Add `{error && <p className={styles.apiError}>{error}</p>}` above submit button
|
|
123
|
+
- Add `{successMsg && <p className={styles.successMsg}>{successMsg}</p>}` for non-nav actions
|
|
124
|
+
- Add useEffect for data-fetching handlers
|
|
125
|
+
- Add .apiError and .successMsg CSS classes to page's .module.css
|
|
126
|
+
10. Call `context_write` — append to context.services[<n>].integrated_pages
|
|
18
127
|
|
|
19
128
|
## File Structure
|
|
20
129
|
```
|
|
21
|
-
<
|
|
130
|
+
<service_name>/
|
|
22
131
|
public/
|
|
23
|
-
assets/css/style.css
|
|
24
|
-
index.html
|
|
25
|
-
.htaccess
|
|
132
|
+
assets/css/style.css ← global styles
|
|
133
|
+
index.html ← single HTML shell
|
|
134
|
+
.htaccess ← SPA routing
|
|
26
135
|
src/
|
|
27
136
|
api/
|
|
28
|
-
apiClient.js
|
|
29
|
-
apiHandler.js
|
|
30
|
-
components/
|
|
31
|
-
pages
|
|
137
|
+
apiClient.js ← Axios + encrypt/decrypt interceptors
|
|
138
|
+
apiHandler.js ← all API call functions
|
|
139
|
+
components/ ← shared reusable components
|
|
140
|
+
pages/<PageName>/ ← one directory per page
|
|
32
141
|
index.jsx
|
|
33
|
-
|
|
34
|
-
App.jsx
|
|
35
|
-
index.jsx
|
|
36
|
-
.env
|
|
37
|
-
.env.example
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## apiClient.js — 4 Responsibilities
|
|
41
|
-
1. Static headers: `api-key`, `Accept-Language`, `Content-Type: text/plain`
|
|
42
|
-
2. Request: encrypt body via AES-256-CBC; attach encrypted `token` from `localStorage('wa_token')` if present
|
|
43
|
-
3. Response success: decrypt body; parse JSON; if `status === -1` → `logOutRedirectCall()`; if decrypt fails → return raw
|
|
44
|
-
4. Response error: `ERR_NETWORK` or `401` → `logOutRedirectCall()` + `showErrorMessage()`
|
|
45
|
-
|
|
46
|
-
KEY/IV: `CryptoJS.enc.Hex.parse(process.env.REACT_APP_KEY/IV)`.
|
|
47
|
-
`logOutRedirectCall` and `showErrorMessage` imported from `../pages/common/Utils`.
|
|
48
|
-
|
|
49
|
-
## apiHandler.js — Pattern
|
|
50
|
-
```javascript
|
|
51
|
-
export const functionName = async (data) => {
|
|
52
|
-
const res = await axiosClient.post('/path', data);
|
|
53
|
-
return res.data;
|
|
54
|
-
};
|
|
55
|
-
```
|
|
56
|
-
- One async function per endpoint — no try/catch, no decryption
|
|
57
|
-
- Session saving in handler, not in UI components
|
|
58
|
-
- Functions match routes in `context.api_routes` for linked service
|
|
59
|
-
|
|
60
|
-
## Code Style
|
|
61
|
-
- Functional components only — no class components
|
|
62
|
-
- JSDoc above every exported function and component
|
|
63
|
-
- No inline styles — `.module.css` per page, `global.css` shared
|
|
64
|
-
- No `console.log` — use `showMessage` / `showErrorMessage`
|
|
65
|
-
- No hardcoded API paths — all calls through `apiHandler.js`
|
|
66
|
-
|
|
67
|
-
## .env Contents
|
|
142
|
+
<PageName>.module.css
|
|
143
|
+
App.jsx ← React Router root
|
|
144
|
+
index.jsx ← ReactDOM.createRoot entry
|
|
145
|
+
.env ← REACT_APP_* (gitignored)
|
|
146
|
+
.env.example
|
|
68
147
|
```
|
|
69
|
-
REACT_APP_BASE_URL=http://localhost:<linked_port>/api/v1/
|
|
70
|
-
REACT_APP_API_KEY=<inherited>
|
|
71
|
-
REACT_APP_KEY=<inherited>
|
|
72
|
-
REACT_APP_IV=<inherited>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## @modularize
|
|
76
|
-
Scan pages, find repeated layout blocks, extract to `src/components/<Name>/`.
|
|
77
|
-
Rewrite pages to use component. Never change data-fetching or state.
|
|
78
|
-
|
|
79
|
-
## @validate-page
|
|
80
|
-
Client-side only. Per-field error messages below inputs. Preferred library from user.
|
|
81
|
-
|
|
82
|
-
## @integrate-api
|
|
83
|
-
Add handler in `apiHandler.js`. Wire buttons/forms. Add loading, error, success states.
|