rbin-task-flow 1.7.0 → 1.9.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.
|
@@ -91,6 +91,31 @@ In **front web** (Next.js, React) or **mobile** (Expo, React Native) projects, e
|
|
|
91
91
|
|
|
92
92
|
The `app/` directory contains ONLY route definitions. Each file is a thin wrapper that imports and renders the feature page/screen.
|
|
93
93
|
|
|
94
|
+
### Next.js App Router — Route groups in app/
|
|
95
|
+
|
|
96
|
+
In **Next.js App Router** projects, organize `app/` with route groups:
|
|
97
|
+
|
|
98
|
+
- **`(public)/`** — Public routes (login, signup, landing, etc.)
|
|
99
|
+
- **`(private)/`** — Private routes (dashboard, profile, etc.; protect via layout or middleware)
|
|
100
|
+
- **`(server)/`** — API / server routes (Route Handlers, e.g. `route.ts`)
|
|
101
|
+
|
|
102
|
+
Example structure:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
app/
|
|
106
|
+
├── (public)/
|
|
107
|
+
│ ├── login/page.tsx
|
|
108
|
+
│ └── signup/page.tsx
|
|
109
|
+
├── (private)/
|
|
110
|
+
│ ├── dashboard/page.tsx
|
|
111
|
+
│ └── admin/question/page.tsx
|
|
112
|
+
├── (server)/
|
|
113
|
+
│ └── api/
|
|
114
|
+
│ └── .../route.ts
|
|
115
|
+
├── layout.tsx
|
|
116
|
+
└── ...
|
|
117
|
+
```
|
|
118
|
+
|
|
94
119
|
**Front-end (Next.js App Router or React):**
|
|
95
120
|
```typescript
|
|
96
121
|
// src/app/(private)/dashboard/page.tsx
|
|
@@ -133,7 +158,7 @@ export class CreateSessionController {
|
|
|
133
158
|
**Rules:**
|
|
134
159
|
- **Front-end/Mobile**: `page.tsx` / route files NEVER contain logic, state, or imports beyond the feature component
|
|
135
160
|
- **Backend**: `app/` contains controllers and validators only — no business logic
|
|
136
|
-
-
|
|
161
|
+
- **Next.js App Router**: Use `(public)/` for public routes, `(private)/` for private routes, `(server)/` for API/Route Handlers. Other React front-ends and mobile may use only `(public)` and `(private)` as needed.
|
|
137
162
|
- `layout.tsx` files may contain auth guards and providers
|
|
138
163
|
- All business logic lives in `features/`
|
|
139
164
|
|
|
@@ -279,36 +304,78 @@ export function DashboardPage() {
|
|
|
279
304
|
}
|
|
280
305
|
```
|
|
281
306
|
|
|
282
|
-
###
|
|
307
|
+
### Page-specific component naming (Front web & Mobile)
|
|
283
308
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
-
|
|
309
|
+
When a component is specific to a page (lives under `features/[feature]/components/`), it must use the **page prefix** in the file name and in the function name.
|
|
310
|
+
|
|
311
|
+
**File names (kebab-case):**
|
|
312
|
+
- Page: `[page-name].page.tsx` → e.g. `admin-question.page.tsx`
|
|
313
|
+
- Page-specific components: prefix = page name (no `.page`) → `admin-question-card.tsx`, `admin-question-card-item.tsx`
|
|
314
|
+
- A **child component** of another component stays in the same `components/` folder (same level as parent) and **inherits the parent prefix**: `admin-question-card-item.tsx` (child of `admin-question-card.tsx`). No subfolders.
|
|
315
|
+
|
|
316
|
+
**Function/component names (PascalCase):**
|
|
317
|
+
- Route in `app/`: one word from route + page name → `AdminQuestion` (export default)
|
|
318
|
+
- Page in features: page name + `Page` → `AdminQuestionPage`
|
|
319
|
+
- Components: PascalCase of the file name → `AdminQuestionCard`, `AdminQuestionCardItem`
|
|
320
|
+
|
|
321
|
+
| Location | File | Export name |
|
|
322
|
+
|----------|------|-------------|
|
|
323
|
+
| `app/(private)/admin/question/page.tsx` | (route file) | `AdminQuestion` (default) |
|
|
324
|
+
| `features/admin/question/pages/admin-question.page.tsx` | `admin-question.page.tsx` | `AdminQuestionPage` |
|
|
325
|
+
| `features/admin/question/components/admin-question-card.tsx` | `admin-question-card.tsx` | `AdminQuestionCard` |
|
|
326
|
+
| `features/admin/question/components/admin-question-card-item.tsx` | `admin-question-card-item.tsx` | `AdminQuestionCardItem` |
|
|
288
327
|
|
|
289
328
|
```typescript
|
|
290
|
-
// src/
|
|
291
|
-
import {
|
|
292
|
-
import { Skeleton } from '@/shared/components/skeleton'
|
|
329
|
+
// src/app/(private)/admin/question/page.tsx
|
|
330
|
+
import { AdminQuestionPage } from '@/features/admin/question/pages/admin-question.page'
|
|
293
331
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
isLoading: boolean
|
|
297
|
-
isError: boolean
|
|
332
|
+
export default function AdminQuestion() {
|
|
333
|
+
return <AdminQuestionPage />
|
|
298
334
|
}
|
|
335
|
+
```
|
|
299
336
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
337
|
+
```typescript
|
|
338
|
+
// src/features/admin/question/pages/admin-question.page.tsx
|
|
339
|
+
'use client'
|
|
340
|
+
|
|
341
|
+
import { AdminQuestionCard } from '@/features/admin/question/components/admin-question-card'
|
|
342
|
+
|
|
343
|
+
export function AdminQuestionPage() {
|
|
344
|
+
return (
|
|
345
|
+
<section>
|
|
346
|
+
<AdminQuestionCard />
|
|
347
|
+
</section>
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
// src/features/admin/question/components/admin-question-card.tsx
|
|
354
|
+
import { AdminQuestionCardItem } from '@/features/admin/question/components/admin-question-card-item'
|
|
303
355
|
|
|
356
|
+
export function AdminQuestionCard() {
|
|
304
357
|
return (
|
|
305
|
-
<
|
|
306
|
-
<
|
|
307
|
-
</
|
|
358
|
+
<ul>
|
|
359
|
+
<AdminQuestionCardItem />
|
|
360
|
+
</ul>
|
|
308
361
|
)
|
|
309
362
|
}
|
|
310
363
|
```
|
|
311
364
|
|
|
365
|
+
```typescript
|
|
366
|
+
// src/features/admin/question/components/admin-question-card-item.tsx
|
|
367
|
+
export function AdminQuestionCardItem() {
|
|
368
|
+
return <li>...</li>
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Components — Single Responsibility
|
|
373
|
+
|
|
374
|
+
Each component has a single responsibility. Components:
|
|
375
|
+
- Receive data via props (no direct service calls unless truly necessary)
|
|
376
|
+
- Follow the **page prefix** naming above when they are page-specific (inside a feature)
|
|
377
|
+
- Stay small and focused; child components stay in the same `components/` folder with the inherited prefix in the name
|
|
378
|
+
|
|
312
379
|
---
|
|
313
380
|
|
|
314
381
|
## shared/ — Global Reusable Code
|
|
@@ -751,3 +818,4 @@ export const useAuth = () => useContext(AuthContext)
|
|
|
751
818
|
9. **Shared is truly shared**: Only put in `shared/` what is used by 2+ features.
|
|
752
819
|
10. **Naming reflects role**: File name + suffix must make the file's purpose immediately obvious.
|
|
753
820
|
11. **No barrel files for re-exports**: Do not use `index.ts` (or `index.tsx`) only to re-export other modules. Import directly from the source file (e.g. `from '@/shared/components/button'` not `from '@/shared/components'`). An `index.ts` is only allowed when it contains real logic or composition, not mere re-exports.
|
|
821
|
+
12. **Page-specific components use page prefix**: In features, the page file is `[page-name].page.tsx`; components specific to that page use the same prefix in file and function name (e.g. `admin-question-card.tsx` → `AdminQuestionCard`). Child components stay in the same `components/` folder and inherit the parent prefix (e.g. `admin-question-card-item.tsx` → `AdminQuestionCardItem`). App route exports `AdminQuestion`, feature page exports `AdminQuestionPage`.
|