rbin-task-flow 1.6.0 → 1.8.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.
@@ -21,12 +21,42 @@ src/
21
21
  └── shared/ # Global reusable code
22
22
  ```
23
23
 
24
+ ### Allowed folders in shared/ and features/ (Front web & Mobile only)
25
+
26
+ In **front web** (Next.js, React, or other React-based web) or **mobile** (Expo, React Native) projects, only the following folder names may exist directly under `shared/` or under each feature in `features/`:
27
+
28
+ | Folder | Use |
29
+ |---------------|------------------------|
30
+ | `pages/` | Web only — page components |
31
+ | `screens/` | Mobile only — screen components |
32
+ | `components/` | UI components |
33
+ | `constants/` | Constants |
34
+ | `utils/` | Utilities |
35
+ | `validations/` | Validation helpers (e.g. `.validation.ts` for Zod) |
36
+ | `hooks/` | Custom hooks |
37
+ | `providers/` | Context providers |
38
+ | `styles/` | Styles |
39
+ | `types/` | TypeScript types |
40
+ | `libs/` | Library wrappers |
41
+ | `services/` | React Query / API wrappers |
42
+ | `use-cases/` | Pure API / business logic |
43
+ | `schemas/` | Zod (or similar) schemas |
44
+
45
+ **No other folder names** are allowed under `shared/` or under `features/[feature-name]/`. Use only `pages/` for web and `screens/` for mobile; do not mix both in the same project type.
46
+
47
+ ### No subfolders in shared/ (Front web & Mobile only)
48
+
49
+ In **front web** (Next.js, React) or **mobile** (Expo, React Native) projects, each folder under `shared/` must be **flat**: no subfolders. Files assume the responsibility through clear naming.
50
+
51
+ - **shared/components/**: One file per component, directly in `shared/components/`. No nested folders (e.g. no `form/`, `inputs/`). Name files so the purpose is clear (e.g. `button.tsx`, `input-text.tsx`, `input-container.tsx`, `input-error.tsx`, `input-label.tsx`).
52
+ - **shared/hooks/**, **shared/utils/**, **shared/validations/**, **shared/constants/**, etc.: Same rule — only files, no subfolders. Use the file name to carry the responsibility. Validation helpers (e.g. `required-email.validation.ts`) live in `shared/validations/`.
53
+
24
54
  ---
25
55
 
26
56
  ## Tech Stack
27
57
 
28
- ### Front-end (Next.js)
29
- - **Framework**: Next.js 15+ with App Router
58
+ ### Front-end (Next.js / React)
59
+ - **Framework**: Next.js 15+ with App Router, or React (Vite, CRA, or similar). These rules apply to any React-based web project.
30
60
  - **Language**: TypeScript (strict mode)
31
61
  - **Styling**: Tailwind CSS v4 + `clsx` + `tailwind-merge` via `cn()` helper
32
62
  - **UI Components**: shadcn/ui + `lucide-react` icons
@@ -37,7 +67,7 @@ src/
37
67
  - **E2E Testing**: Playwright and/or Cypress
38
68
 
39
69
  ### Mobile (Expo / React Native)
40
- - **Framework**: Expo with Expo Router
70
+ - **Framework**: Expo with Expo Router, or React Native (bare or managed). These rules apply to both Expo and React Native.
41
71
  - **Language**: TypeScript (strict mode)
42
72
  - **Styling**: NativeWind + `clsx` + `tailwind-merge` via `cn()` helper
43
73
  - **Data Fetching**: `@tanstack/react-query`
@@ -61,7 +91,7 @@ src/
61
91
 
62
92
  The `app/` directory contains ONLY route definitions. Each file is a thin wrapper that imports and renders the feature page/screen.
63
93
 
64
- **Front-end (Next.js App Router):**
94
+ **Front-end (Next.js App Router or React):**
65
95
  ```typescript
66
96
  // src/app/(private)/dashboard/page.tsx
67
97
  import { DashboardPage } from '@/features/dashboard/pages/dashboard.page'
@@ -71,7 +101,7 @@ export default function Dashboard() {
71
101
  }
72
102
  ```
73
103
 
74
- **Mobile (Expo Router):**
104
+ **Mobile (Expo Router or React Native):**
75
105
  ```typescript
76
106
  // src/app/(private)/dashboard.tsx
77
107
  import { DashboardScreen } from '@/features/dashboard/screens/dashboard.screen'
@@ -249,40 +279,84 @@ export function DashboardPage() {
249
279
  }
250
280
  ```
251
281
 
252
- ### Components Single Responsibility
282
+ ### Page-specific component naming (Front web & Mobile)
253
283
 
254
- Each component has a single responsibility. Components:
255
- - Receive data via props (no direct service calls unless truly necessary)
256
- - Are named after the feature: `[feature]-[description].tsx`
257
- - Stay small and focused
284
+ 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.
285
+
286
+ **File names (kebab-case):**
287
+ - Page: `[page-name].page.tsx` e.g. `admin-question.page.tsx`
288
+ - Page-specific components: prefix = page name (no `.page`) → `admin-question-card.tsx`, `admin-question-card-item.tsx`
289
+ - 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.
290
+
291
+ **Function/component names (PascalCase):**
292
+ - Route in `app/`: one word from route + page name → `AdminQuestion` (export default)
293
+ - Page in features: page name + `Page` → `AdminQuestionPage`
294
+ - Components: PascalCase of the file name → `AdminQuestionCard`, `AdminQuestionCardItem`
295
+
296
+ | Location | File | Export name |
297
+ |----------|------|-------------|
298
+ | `app/(private)/admin/question/page.tsx` | (route file) | `AdminQuestion` (default) |
299
+ | `features/admin/question/pages/admin-question.page.tsx` | `admin-question.page.tsx` | `AdminQuestionPage` |
300
+ | `features/admin/question/components/admin-question-card.tsx` | `admin-question-card.tsx` | `AdminQuestionCard` |
301
+ | `features/admin/question/components/admin-question-card-item.tsx` | `admin-question-card-item.tsx` | `AdminQuestionCardItem` |
258
302
 
259
303
  ```typescript
260
- // src/features/dashboard/components/dashboard-active-card.tsx
261
- import { Card } from '@/shared/components/card'
262
- import { Skeleton } from '@/shared/components/skeleton'
304
+ // src/app/(private)/admin/question/page.tsx
305
+ import { AdminQuestionPage } from '@/features/admin/question/pages/admin-question.page'
263
306
 
264
- type DashboardActiveCardProps = {
265
- data?: { count: number; trials: number }
266
- isLoading: boolean
267
- isError: boolean
307
+ export default function AdminQuestion() {
308
+ return <AdminQuestionPage />
268
309
  }
310
+ ```
269
311
 
270
- export function DashboardActiveCard({ data, isLoading, isError }: DashboardActiveCardProps) {
271
- if (isLoading) return <Skeleton className="h-[200px]" />
272
- if (isError) return <ErrorState />
312
+ ```typescript
313
+ // src/features/admin/question/pages/admin-question.page.tsx
314
+ 'use client'
315
+
316
+ import { AdminQuestionCard } from '@/features/admin/question/components/admin-question-card'
317
+
318
+ export function AdminQuestionPage() {
319
+ return (
320
+ <section>
321
+ <AdminQuestionCard />
322
+ </section>
323
+ )
324
+ }
325
+ ```
273
326
 
327
+ ```typescript
328
+ // src/features/admin/question/components/admin-question-card.tsx
329
+ import { AdminQuestionCardItem } from '@/features/admin/question/components/admin-question-card-item'
330
+
331
+ export function AdminQuestionCard() {
274
332
  return (
275
- <Card title="Active Members">
276
- <p className="text-2xl font-bold">{data?.count}</p>
277
- </Card>
333
+ <ul>
334
+ <AdminQuestionCardItem />
335
+ </ul>
278
336
  )
279
337
  }
280
338
  ```
281
339
 
340
+ ```typescript
341
+ // src/features/admin/question/components/admin-question-card-item.tsx
342
+ export function AdminQuestionCardItem() {
343
+ return <li>...</li>
344
+ }
345
+ ```
346
+
347
+ ### Components — Single Responsibility
348
+
349
+ Each component has a single responsibility. Components:
350
+ - Receive data via props (no direct service calls unless truly necessary)
351
+ - Follow the **page prefix** naming above when they are page-specific (inside a feature)
352
+ - Stay small and focused; child components stay in the same `components/` folder with the inherited prefix in the name
353
+
282
354
  ---
283
355
 
284
356
  ## shared/ — Global Reusable Code
285
357
 
358
+ In front web (Next.js, React) and mobile (Expo, React Native), `shared/` is flat per folder (no subfolders). One file per concern; naming carries the responsibility.
359
+
286
360
  ```
287
361
  shared/
288
362
  ├── components/
@@ -291,14 +365,11 @@ shared/
291
365
  │ ├── data-handler.tsx
292
366
  │ ├── skeleton.tsx
293
367
  │ ├── dialog.tsx
294
- └── form/
295
- └── inputs/
296
- ├── input-text.tsx
297
- ├── input-select.tsx
298
- └── shared/
299
- │ ├── input-container.tsx
300
- │ ├── input-error.tsx
301
- │ └── input-label.tsx
368
+ ├── input-text.tsx
369
+ ├── input-select.tsx
370
+ ├── input-container.tsx
371
+ ├── input-error.tsx
372
+ └── input-label.tsx
302
373
  ├── hooks/
303
374
  │ ├── dialog.hook.tsx
304
375
  │ └── drawer.hook.tsx
@@ -312,11 +383,11 @@ shared/
312
383
  │ └── shared.ui.type.ts
313
384
  ├── constants/
314
385
  │ └── server-routes.constants.ts
386
+ ├── validations/
387
+ │ ├── required-email.validation.ts
388
+ │ ├── required-string.validation.ts
389
+ │ └── required-phone.validation.ts
315
390
  └── utils/
316
- ├── validation/
317
- │ ├── required-email.validation.ts
318
- │ ├── required-string.validation.ts
319
- │ └── required-phone.validation.ts
320
391
  └── error.util.ts
321
392
  ```
322
393
 
@@ -516,8 +587,8 @@ export type ServiceInput<TData = unknown> = {
516
587
  ```typescript
517
588
  // src/features/auth/schemas/login.schema.ts
518
589
  import { z } from 'zod'
519
- import { requiredEmail } from '@/shared/utils/validation/required-email.validation'
520
- import { requiredString } from '@/shared/utils/validation/required-string.validation'
590
+ import { requiredEmail } from '@/shared/validations/required-email.validation'
591
+ import { requiredString } from '@/shared/validations/required-string.validation'
521
592
 
522
593
  export const loginSchema = z.object({
523
594
  email: requiredEmail(),
@@ -529,7 +600,7 @@ export type LoginSchema = z.infer<typeof loginSchema>
529
600
 
530
601
  **Reusable validators in shared/:**
531
602
  ```typescript
532
- // src/shared/utils/validation/required-string.validation.ts
603
+ // src/shared/validations/required-string.validation.ts
533
604
  import { z } from 'zod'
534
605
 
535
606
  export const requiredString = ({ field, min = 1 }: { field: string; min?: number }) =>
@@ -547,7 +618,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
547
618
  import { useForm } from 'react-hook-form'
548
619
  import { LoginSchema, loginSchema } from '@/features/auth/schemas/login.schema'
549
620
  import { SessionCreateService } from '@/features/auth/services/session-create.service'
550
- import { InputText } from '@/shared/components/form/inputs/input-text'
621
+ import { InputText } from '@/shared/components/input-text'
551
622
  import { Button } from '@/shared/components/button'
552
623
 
553
624
  export function LoginForm() {
@@ -572,7 +643,7 @@ export function LoginForm() {
572
643
 
573
644
  **Input uses `Controller` from RHF and is generic:**
574
645
  ```typescript
575
- // src/shared/components/form/inputs/input-text.tsx
646
+ // src/shared/components/input-text.tsx
576
647
  import { Control, Controller, FieldValues, Path, PathValue } from 'react-hook-form'
577
648
  import { cn } from '@/shared/libs/tw-merge'
578
649
 
@@ -616,13 +687,24 @@ export function InputText<T extends FieldValues>({
616
687
 
617
688
  ## File Naming Conventions
618
689
 
619
- Use kebab-case for all filenames. Suffix reflects the file's role:
690
+ ### Rule for front (web & mobile): outside `app/` only
691
+
692
+ Every file outside the `app/` folder must follow:
693
+
694
+ - **Format**: lowercase, words separated by `-`, then `.tipo.ext` (suffix by role).
695
+ - **Examples**: `pagina-exemplo.page.tsx`, `login.schema.ts`, `session-create.use-case.ts`, `dashboard-active.type.ts`.
696
+
697
+ **Components are the exception**: do **not** use a `.component` suffix. Use only kebab-case + extension, e.g. `pagina-exemplo.tsx`, `dashboard-revenue-card.tsx`, `input-text.tsx`.
698
+
699
+ **Another exception**: files inside any `styles/` folder do not need to follow this pattern (e.g. CSS/SCSS modules may use their own convention).
700
+
701
+ ### Suffix by role
620
702
 
621
703
  | Role | Suffix | Example |
622
704
  |------|--------|---------|
623
- | Page component | `.page.tsx` | `dashboard.page.tsx` |
705
+ | Page component | `.page.tsx` | `pagina-exemplo.page.tsx` |
624
706
  | Screen component (mobile) | `.screen.tsx` | `login.screen.tsx` |
625
- | UI component | `.tsx` | `dashboard-revenue-card.tsx` |
707
+ | UI component | (no suffix) `.tsx` | `dashboard-revenue-card.tsx`, `input-text.tsx` |
626
708
  | React Query service | `.service.tsx` | `session-create.service.tsx` |
627
709
  | API call (pure) | `.use-case.ts` | `session-create.use-case.ts` |
628
710
  | Zod schema | `.schema.ts` | `login.schema.ts` |
@@ -630,7 +712,7 @@ Use kebab-case for all filenames. Suffix reflects the file's role:
630
712
  | API response type | `.api.type.ts` | `session.api.type.ts` |
631
713
  | Domain type | `.type.ts` | `dashboard-active.type.ts` |
632
714
  | Utility | `.util.ts` | `error.util.ts` |
633
- | Validation helper | `.validation.ts` | `required-email.validation.ts` |
715
+ | Validation helper | `.validation.ts` | `required-email.validation.ts` (in `validations/`) |
634
716
  | Constants | `.constants.ts` | `server-routes.constants.ts` |
635
717
 
636
718
  ---
@@ -684,7 +766,7 @@ export const useAuth = () => useContext(AuthContext)
684
766
 
685
767
  ## Testing
686
768
 
687
- ### Front-end (Next.js)
769
+ ### Front-end (Next.js / React)
688
770
  - **E2E**: Playwright and/or Cypress
689
771
  - Tests live in `e2e/` or `cypress/` at project root
690
772
  - Test files: `[feature].spec.ts` (Playwright) or `[feature].cy.ts` (Cypress)
@@ -710,3 +792,5 @@ export const useAuth = () => useContext(AuthContext)
710
792
  8. **Type everything**: No `any`. All props, params, and return values must be typed.
711
793
  9. **Shared is truly shared**: Only put in `shared/` what is used by 2+ features.
712
794
  10. **Naming reflects role**: File name + suffix must make the file's purpose immediately obvious.
795
+ 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.
796
+ 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`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rbin-task-flow",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "AI-powered task management for Claude and Cursor",
5
5
  "main": "index.js",
6
6
  "bin": {