generator-kodly-react-app 1.0.6 → 1.0.10
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/generators/app/index.js +63 -11
- package/generators/app/templates/.env.dev +4 -0
- package/generators/app/templates/.env.sandbox +4 -0
- package/generators/app/templates/STRUCTURE.md +661 -0
- package/generators/app/templates/components.json +22 -0
- package/generators/app/templates/index.html +14 -6
- package/generators/app/templates/openapi-ts.config.ts +29 -0
- package/generators/app/templates/package.json +46 -26
- package/generators/app/templates/public/favicon.svg +4 -0
- package/generators/app/templates/src/app.tsx +8 -8
- package/generators/app/templates/src/components/layout/language-switcher.tsx +40 -0
- package/generators/app/templates/src/components/layout/theme-switcher.tsx +37 -0
- package/generators/app/templates/src/components/theme/theme-provider.tsx +22 -28
- package/generators/app/templates/src/components/ui/button.tsx +34 -32
- package/generators/app/templates/src/components/ui/card.tsx +76 -0
- package/generators/app/templates/src/components/ui/field.tsx +242 -0
- package/generators/app/templates/src/components/ui/form.tsx +129 -0
- package/generators/app/templates/src/components/ui/input-group.tsx +170 -0
- package/generators/app/templates/src/components/ui/input.tsx +19 -21
- package/generators/app/templates/src/components/ui/label.tsx +24 -0
- package/generators/app/templates/src/components/ui/select.tsx +184 -0
- package/generators/app/templates/src/components/ui/separator.tsx +31 -0
- package/generators/app/templates/src/components/ui/textarea.tsx +22 -0
- package/generators/app/templates/src/index.css +83 -26
- package/generators/app/templates/src/lib/api/client.ts +4 -5
- package/generators/app/templates/src/lib/i18n.ts +31 -16
- package/generators/app/templates/src/lib/routes.ts +14 -0
- package/generators/app/templates/src/lib/utils/error-handler.ts +7 -2
- package/generators/app/templates/src/lib/utils/init-form-schema.ts +12 -0
- package/generators/app/templates/src/lib/utils.ts +3 -4
- package/generators/app/templates/src/locales/en/common.json +5 -0
- package/generators/app/templates/src/locales/en/theme.json +5 -0
- package/generators/app/templates/src/locales/index.ts +31 -0
- package/generators/app/templates/src/locales/ja/common.json +5 -0
- package/generators/app/templates/src/locales/ja/theme.json +6 -0
- package/generators/app/templates/src/main.tsx +19 -15
- package/generators/app/templates/src/modules/app/layouts/app-layout.tsx +37 -0
- package/generators/app/templates/src/modules/app/locales/app-en.json +9 -0
- package/generators/app/templates/src/modules/app/locales/app-ja.json +9 -0
- package/generators/app/templates/src/modules/auth/components/forgot-password-form.tsx +74 -0
- package/generators/app/templates/src/modules/auth/components/login-form.tsx +95 -0
- package/generators/app/templates/src/modules/auth/components/reset-password-form.tsx +112 -0
- package/generators/app/templates/src/modules/auth/components/signup-form.tsx +92 -0
- package/generators/app/templates/src/modules/auth/contexts/auth-context.tsx +11 -0
- package/generators/app/templates/src/modules/auth/hooks/use-auth-hook.ts +175 -0
- package/generators/app/templates/src/modules/auth/layouts/auth-layout.tsx +28 -0
- package/generators/app/templates/src/modules/auth/locales/auth-en.json +105 -0
- package/generators/app/templates/src/modules/auth/locales/auth-ja.json +105 -0
- package/generators/app/templates/src/modules/landing/components/auth-hero.tsx +34 -0
- package/generators/app/templates/src/modules/landing/components/welcome-hero.tsx +24 -0
- package/generators/app/templates/src/modules/landing/landing-page-layout.tsx +24 -0
- package/generators/app/templates/src/modules/landing/landing-page.tsx +17 -0
- package/generators/app/templates/src/modules/landing/layouts/landing-page-layout.tsx +24 -0
- package/generators/app/templates/src/modules/landing/locales/landing-en.json +12 -0
- package/generators/app/templates/src/modules/landing/locales/landing-ja.json +11 -0
- package/generators/app/templates/src/openapi-client-config.ts +6 -0
- package/generators/app/templates/src/routeTree.gen.ts +268 -3
- package/generators/app/templates/src/router.tsx +2 -2
- package/generators/app/templates/src/routes/__root.tsx +3 -3
- package/generators/app/templates/src/routes/_landing/index.tsx +10 -0
- package/generators/app/templates/src/routes/_landing/route.tsx +14 -0
- package/generators/app/templates/src/routes/app/index.tsx +4 -21
- package/generators/app/templates/src/routes/app/route.tsx +12 -8
- package/generators/app/templates/src/routes/auth/forgot-password.tsx +10 -0
- package/generators/app/templates/src/routes/auth/login.tsx +6 -7
- package/generators/app/templates/src/routes/auth/reset-password.tsx +15 -0
- package/generators/app/templates/src/routes/auth/route.tsx +23 -6
- package/generators/app/templates/src/routes/auth/signup.tsx +11 -0
- package/generators/app/templates/src/sdk/@tanstack/react-query.gen.ts +91 -0
- package/generators/app/templates/src/sdk/client/client.gen.ts +167 -0
- package/generators/app/templates/src/sdk/client/index.ts +23 -0
- package/generators/app/templates/src/sdk/client/types.gen.ts +197 -0
- package/generators/app/templates/src/sdk/client/utils.gen.ts +213 -0
- package/generators/app/templates/src/sdk/client.gen.ts +18 -0
- package/generators/app/templates/src/sdk/core/auth.gen.ts +42 -0
- package/generators/app/templates/src/sdk/core/bodySerializer.gen.ts +100 -0
- package/generators/app/templates/src/sdk/core/params.gen.ts +176 -0
- package/generators/app/templates/src/sdk/core/pathSerializer.gen.ts +181 -0
- package/generators/app/templates/src/sdk/core/queryKeySerializer.gen.ts +136 -0
- package/generators/app/templates/src/sdk/core/serverSentEvents.gen.ts +266 -0
- package/generators/app/templates/src/sdk/core/types.gen.ts +118 -0
- package/generators/app/templates/src/sdk/core/utils.gen.ts +143 -0
- package/generators/app/templates/src/sdk/index.ts +4 -0
- package/generators/app/templates/src/sdk/schemas.gen.ts +195 -0
- package/generators/app/templates/src/sdk/sdk.gen.ts +80 -0
- package/generators/app/templates/src/sdk/types.gen.ts +158 -0
- package/generators/app/templates/src/sdk/zod.gen.ts +148 -0
- package/generators/app/templates/src/vite-env.d.ts +2 -1
- package/generators/app/templates/tsconfig.json +1 -1
- package/generators/app/templates/vite.config.js +35 -21
- package/generators/constants.js +9 -9
- package/package.json +3 -2
- package/generators/app/templates/.env.example +0 -5
- package/generators/app/templates/README.md +0 -57
- package/generators/app/templates/src/locales/en.json +0 -18
- package/generators/app/templates/src/modules/auth/auth-context.tsx +0 -13
- package/generators/app/templates/src/modules/auth/login/login-form.tsx +0 -49
- package/generators/app/templates/src/modules/auth/login/login-page.tsx +0 -12
- package/generators/app/templates/src/modules/auth/use-auth-hook.ts +0 -87
- package/generators/app/templates/src/routes/index.tsx +0 -12
- package/generators/app/templates/types.d.ts +0 -3
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
# React App Template Structure Guide
|
|
2
|
+
|
|
3
|
+
This document explains the directory structure and organization patterns used in this React application template. Understanding this structure will help you add new features, modules, and components in a consistent manner.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Overview](#overview)
|
|
8
|
+
2. [Root Level Files](#root-level-files)
|
|
9
|
+
3. [Source Directory (`src/`)](#source-directory-src)
|
|
10
|
+
4. [Module Structure](#module-structure)
|
|
11
|
+
5. [Routes Structure](#routes-structure)
|
|
12
|
+
6. [Components Organization](#components-organization)
|
|
13
|
+
7. [Localization (i18n) Structure](#localization-i18n-structure)
|
|
14
|
+
8. [Adding a New Module](#adding-a-new-module)
|
|
15
|
+
9. [Naming Conventions](#naming-conventions)
|
|
16
|
+
10. [File Patterns](#file-patterns)
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
This React application follows a **feature-based modular architecture** where related functionality is grouped into self-contained modules. Each module contains its own components, layouts, hooks, contexts, and translations.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
templates/
|
|
24
|
+
├── src/ # Source code
|
|
25
|
+
│ ├── components/ # Shared/reusable components
|
|
26
|
+
│ ├── lib/ # Utilities, API clients, shared logic
|
|
27
|
+
│ ├── locales/ # Global translations
|
|
28
|
+
│ ├── modules/ # Feature modules (feature-based organization)
|
|
29
|
+
│ ├── routes/ # TanStack Router route files
|
|
30
|
+
│ ├── sdk/ # Generated API client code
|
|
31
|
+
│ └── types/ # TypeScript type definitions
|
|
32
|
+
├── public/ # Static assets
|
|
33
|
+
├── package.json # Dependencies and scripts
|
|
34
|
+
├── vite.config.js # Vite configuration
|
|
35
|
+
├── tailwind.config.js # Tailwind CSS configuration
|
|
36
|
+
└── tsconfig.json # TypeScript configuration
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Root Level Files
|
|
40
|
+
|
|
41
|
+
### Configuration Files
|
|
42
|
+
|
|
43
|
+
- **`package.json`** - Dependencies, scripts, and project metadata
|
|
44
|
+
- **`vite.config.js`** - Vite bundler configuration
|
|
45
|
+
- **`tsconfig.json`** - TypeScript compiler configuration
|
|
46
|
+
- **`tsconfig.app.json`** - Application-specific TypeScript config
|
|
47
|
+
- **`tailwind.config.js`** - Tailwind CSS configuration
|
|
48
|
+
- **`postcss.config.js`** - PostCSS configuration
|
|
49
|
+
- **`openapi-ts.config.ts`** - OpenAPI TypeScript client generation config
|
|
50
|
+
- **`components.json`** - shadcn/ui components configuration
|
|
51
|
+
- **`.env.sandbox`** - Environment variables for sandbox mode
|
|
52
|
+
|
|
53
|
+
### Template Files
|
|
54
|
+
|
|
55
|
+
- **`index.html`** - HTML entry point
|
|
56
|
+
- **`README.md`** - Project documentation
|
|
57
|
+
- **`gitignore.template`** - Git ignore patterns (copied to `.gitignore`)
|
|
58
|
+
|
|
59
|
+
## Source Directory (`src/`)
|
|
60
|
+
|
|
61
|
+
### Core Application Files
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
src/
|
|
65
|
+
├── main.tsx # Application entry point
|
|
66
|
+
├── app.tsx # Root app component (wraps router with providers)
|
|
67
|
+
├── router.tsx # Router configuration
|
|
68
|
+
├── routeTree.gen.ts # Generated route tree (auto-generated)
|
|
69
|
+
├── index.css # Global styles
|
|
70
|
+
├── vite-env.d.ts # Vite type definitions
|
|
71
|
+
├── openapi-client-config.ts # OpenAPI client configuration
|
|
72
|
+
└── types/
|
|
73
|
+
└── i18n.d.ts # i18n TypeScript definitions
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Key Directories
|
|
77
|
+
|
|
78
|
+
#### `src/components/` - Shared Components
|
|
79
|
+
|
|
80
|
+
Reusable components used across multiple modules:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
components/
|
|
84
|
+
├── layout/ # Layout-related components
|
|
85
|
+
│ ├── language-switcher.tsx
|
|
86
|
+
│ └── theme-switcher.tsx
|
|
87
|
+
├── theme/ # Theme provider components
|
|
88
|
+
│ └── theme-provider.tsx
|
|
89
|
+
└── ui/ # shadcn/ui components (button, card, form, etc.)
|
|
90
|
+
├── button.tsx
|
|
91
|
+
├── card.tsx
|
|
92
|
+
├── field.tsx
|
|
93
|
+
├── form.tsx
|
|
94
|
+
├── input.tsx
|
|
95
|
+
├── label.tsx
|
|
96
|
+
├── select.tsx
|
|
97
|
+
└── ...
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Usage Guidelines:**
|
|
101
|
+
|
|
102
|
+
- Components in `components/ui/` are typically shadcn/ui components (reusable UI primitives)
|
|
103
|
+
- Components in `components/layout/` are shared layout utilities
|
|
104
|
+
- If a component is only used within one module, it should be in that module's `components/` directory
|
|
105
|
+
|
|
106
|
+
#### `src/lib/` - Shared Libraries and Utilities
|
|
107
|
+
|
|
108
|
+
Shared business logic, utilities, and API clients:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
lib/
|
|
112
|
+
├── api/
|
|
113
|
+
│ └── client.ts # API client configuration
|
|
114
|
+
├── utils/
|
|
115
|
+
│ ├── error-handler.ts # Error handling utilities
|
|
116
|
+
│ └── init-form-schema.ts # Form schema initialization
|
|
117
|
+
├── i18n.ts # i18n configuration and utilities
|
|
118
|
+
├── routes.ts # Route constants (e.g., DEFAULT_LOGGED_IN_ROUTE)
|
|
119
|
+
└── utils.ts # General utility functions
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### `src/locales/` - Global Translations
|
|
123
|
+
|
|
124
|
+
Global translations shared across all modules:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
locales/
|
|
128
|
+
├── index.ts # Translation merging and export
|
|
129
|
+
├── en/ # English translations
|
|
130
|
+
│ ├── common.json # Common/shared strings
|
|
131
|
+
│ └── theme.json # Theme-related strings
|
|
132
|
+
└── ja/ # Japanese translations
|
|
133
|
+
├── common.json
|
|
134
|
+
└── theme.json
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### `src/sdk/` - Generated API Client
|
|
138
|
+
|
|
139
|
+
Auto-generated API client code (from OpenAPI specs):
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
sdk/
|
|
143
|
+
├── client/ # Generated client code
|
|
144
|
+
├── core/ # Core SDK utilities
|
|
145
|
+
├── schemas.gen.ts # Generated schemas
|
|
146
|
+
├── types.gen.ts # Generated types
|
|
147
|
+
└── ...
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Note:** This directory is typically generated and should not be manually edited.
|
|
151
|
+
|
|
152
|
+
## Module Structure
|
|
153
|
+
|
|
154
|
+
Modules are **feature-based** self-contained units of functionality. Each module represents a major feature or domain area.
|
|
155
|
+
|
|
156
|
+
### Module Directory Structure
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
modules/
|
|
160
|
+
└── {module-name}/ # e.g., auth, app, landing
|
|
161
|
+
├── components/ # Module-specific components
|
|
162
|
+
├── contexts/ # React contexts (if needed)
|
|
163
|
+
├── hooks/ # Custom React hooks
|
|
164
|
+
├── layouts/ # Layout components for this module
|
|
165
|
+
├── locales/ # Module-specific translations
|
|
166
|
+
│ ├── {module}-en.json
|
|
167
|
+
│ └── {module}-ja.json
|
|
168
|
+
└── {module-page}.tsx # Main page components (optional)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Example: Auth Module
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
modules/auth/
|
|
175
|
+
├── components/
|
|
176
|
+
│ ├── login-form.tsx
|
|
177
|
+
│ ├── signup-form.tsx
|
|
178
|
+
│ ├── forgot-password-form.tsx
|
|
179
|
+
│ └── reset-password-form.tsx
|
|
180
|
+
├── contexts/
|
|
181
|
+
│ └── auth-context.tsx
|
|
182
|
+
├── hooks/
|
|
183
|
+
│ └── use-auth-hook.ts
|
|
184
|
+
├── layouts/
|
|
185
|
+
│ └── auth-layout.tsx
|
|
186
|
+
└── locales/
|
|
187
|
+
├── auth-en.json
|
|
188
|
+
└── auth-ja.json
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Example: App Module
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
modules/app/
|
|
195
|
+
├── components/ # (empty, can add module-specific components)
|
|
196
|
+
├── hooks/ # (empty, can add module-specific hooks)
|
|
197
|
+
├── layouts/
|
|
198
|
+
│ └── app-layout.tsx
|
|
199
|
+
└── locales/
|
|
200
|
+
├── app-en.json
|
|
201
|
+
└── app-ja.json
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Example: Landing Module
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
modules/landing/
|
|
208
|
+
├── components/
|
|
209
|
+
│ ├── auth-hero.tsx
|
|
210
|
+
│ └── welcome-hero.tsx
|
|
211
|
+
├── layouts/
|
|
212
|
+
│ └── landing-page-layout.tsx
|
|
213
|
+
├── locales/
|
|
214
|
+
│ ├── landing-en.json
|
|
215
|
+
│ └── landing-ja.json
|
|
216
|
+
├── landing-page-layout.tsx
|
|
217
|
+
└── landing-page.tsx
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Module File Types
|
|
221
|
+
|
|
222
|
+
1. **Components** (`components/`)
|
|
223
|
+
- Module-specific UI components
|
|
224
|
+
- Use kebab-case: `login-form.tsx`, `user-profile-card.tsx`
|
|
225
|
+
|
|
226
|
+
2. **Contexts** (`contexts/`)
|
|
227
|
+
- React Context providers for module state
|
|
228
|
+
- Use kebab-case: `auth-context.tsx`
|
|
229
|
+
|
|
230
|
+
3. **Hooks** (`hooks/`)
|
|
231
|
+
- Custom React hooks for module logic
|
|
232
|
+
- Use kebab-case with `use-` prefix: `use-auth-hook.ts`
|
|
233
|
+
|
|
234
|
+
4. **Layouts** (`layouts/`)
|
|
235
|
+
- Layout wrappers for module routes
|
|
236
|
+
- Use kebab-case: `auth-layout.tsx`, `app-layout.tsx`
|
|
237
|
+
|
|
238
|
+
5. **Locales** (`locales/`)
|
|
239
|
+
- Translation files following pattern: `{module}-{lang}.json`
|
|
240
|
+
- Example: `auth-en.json`, `auth-ja.json`
|
|
241
|
+
|
|
242
|
+
## Routes Structure
|
|
243
|
+
|
|
244
|
+
Routes follow TanStack Router's file-based routing convention:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
routes/
|
|
248
|
+
├── __root.tsx # Root route (wraps all routes)
|
|
249
|
+
├── $.tsx # 404/fallback route
|
|
250
|
+
├── _landing/ # Route group (underscore prefix)
|
|
251
|
+
│ ├── route.tsx # Parent route for landing group
|
|
252
|
+
│ └── index.tsx # Landing page route (/)
|
|
253
|
+
├── app/ # App routes (authenticated)
|
|
254
|
+
│ ├── route.tsx # Parent route with auth guard
|
|
255
|
+
│ └── index.tsx # App home page (/app)
|
|
256
|
+
└── auth/ # Auth routes (unauthenticated)
|
|
257
|
+
├── route.tsx # Parent route with auth layout
|
|
258
|
+
├── login.tsx # /auth/login
|
|
259
|
+
├── signup.tsx # /auth/signup
|
|
260
|
+
├── forgot-password.tsx # /auth/forgot-password
|
|
261
|
+
└── reset-password.tsx # /auth/reset-password
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Route File Patterns
|
|
265
|
+
|
|
266
|
+
1. **Parent Route** (`route.tsx`)
|
|
267
|
+
- Defines layout and guards for a route group
|
|
268
|
+
- Example: `/auth/route.tsx` wraps all `/auth/*` routes with `AuthLayout`
|
|
269
|
+
|
|
270
|
+
2. **Child Routes**
|
|
271
|
+
- Individual page routes
|
|
272
|
+
- Example: `/auth/login.tsx` renders the login page component
|
|
273
|
+
|
|
274
|
+
3. **Route Groups** (`_{name}/`)
|
|
275
|
+
- Underscore prefix creates a route group
|
|
276
|
+
- Example: `_landing/` groups routes without the prefix in the URL
|
|
277
|
+
|
|
278
|
+
### Route Implementation Pattern
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
// src/routes/{module}/route.tsx (Parent route)
|
|
282
|
+
import { createFileRoute, Outlet } from '@tanstack/react-router';
|
|
283
|
+
import { ModuleLayout } from '@/modules/{module}/layouts/{module}-layout';
|
|
284
|
+
|
|
285
|
+
export const Route = createFileRoute('/{module}')({
|
|
286
|
+
beforeLoad: ({ context }) => {
|
|
287
|
+
// Guards, redirects, etc.
|
|
288
|
+
},
|
|
289
|
+
component: RouteComponent,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
function RouteComponent() {
|
|
293
|
+
return (
|
|
294
|
+
<ModuleLayout>
|
|
295
|
+
<Outlet />
|
|
296
|
+
</ModuleLayout>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
// src/routes/{module}/{page}.tsx (Child route)
|
|
303
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
304
|
+
import { PageComponent } from '@/modules/{module}/components/{page}-component';
|
|
305
|
+
|
|
306
|
+
export const Route = createFileRoute('/{module}/{page}')({
|
|
307
|
+
component: RouteComponent,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
function RouteComponent() {
|
|
311
|
+
return <PageComponent />;
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Components Organization
|
|
316
|
+
|
|
317
|
+
### Shared vs Module-Specific Components
|
|
318
|
+
|
|
319
|
+
**Shared Components** (`src/components/`):
|
|
320
|
+
|
|
321
|
+
- Used across multiple modules
|
|
322
|
+
- Generic, reusable UI primitives
|
|
323
|
+
- Examples: `Button`, `Card`, `Input`, `Form`
|
|
324
|
+
|
|
325
|
+
**Module-Specific Components** (`src/modules/{module}/components/`):
|
|
326
|
+
|
|
327
|
+
- Only used within one module
|
|
328
|
+
- Feature-specific logic
|
|
329
|
+
- Examples: `LoginForm`, `UserProfileCard`, `DashboardWidget`
|
|
330
|
+
|
|
331
|
+
### Component Naming
|
|
332
|
+
|
|
333
|
+
- **File names**: kebab-case (e.g., `login-form.tsx`, `user-profile-card.tsx`)
|
|
334
|
+
- **Component names**: PascalCase (e.g., `LoginForm`, `UserProfileCard`)
|
|
335
|
+
- **Hooks**: kebab-case with `use-` prefix (e.g., `use-auth-hook.ts`)
|
|
336
|
+
|
|
337
|
+
## Localization (i18n) Structure
|
|
338
|
+
|
|
339
|
+
### Translation File Organization
|
|
340
|
+
|
|
341
|
+
Translations are organized in two levels:
|
|
342
|
+
|
|
343
|
+
1. **Global Translations** (`src/locales/`)
|
|
344
|
+
- Shared across all modules
|
|
345
|
+
- Languages: `en/`, `ja/`
|
|
346
|
+
- Files: `common.json`, `theme.json`
|
|
347
|
+
|
|
348
|
+
2. **Module Translations** (`src/modules/{module}/locales/`)
|
|
349
|
+
- Module-specific translations
|
|
350
|
+
- Files: `{module}-en.json`, `{module}-ja.json`
|
|
351
|
+
|
|
352
|
+
### Translation File Naming
|
|
353
|
+
|
|
354
|
+
- Pattern: `{module}-{language}.json`
|
|
355
|
+
- Examples:
|
|
356
|
+
- `auth-en.json`, `auth-ja.json`
|
|
357
|
+
- `app-en.json`, `app-ja.json`
|
|
358
|
+
- `landing-en.json`, `landing-ja.json`
|
|
359
|
+
|
|
360
|
+
### Translation Merging
|
|
361
|
+
|
|
362
|
+
Translations are merged in `src/locales/index.ts`:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
export const mergeTranslations = (lang: SupportedLanguages) => {
|
|
366
|
+
if (lang === 'en') {
|
|
367
|
+
return {
|
|
368
|
+
auth: { ...enAuth },
|
|
369
|
+
app: { ...enApp },
|
|
370
|
+
landing: { ...enLanding },
|
|
371
|
+
common: { ...enCommon },
|
|
372
|
+
theme: { ...enTheme },
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
// ... other languages
|
|
376
|
+
};
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Using Translations in Components
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
import { useTranslation } from 'react-i18next';
|
|
383
|
+
|
|
384
|
+
function MyComponent() {
|
|
385
|
+
const { t } = useTranslation();
|
|
386
|
+
|
|
387
|
+
return (
|
|
388
|
+
<div>
|
|
389
|
+
<h1>{t('auth.login.title')}</h1>
|
|
390
|
+
<p>{t('common.welcome')}</p>
|
|
391
|
+
</div>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Translation keys follow the pattern: `{module}.{section}.{key}`
|
|
397
|
+
|
|
398
|
+
## Adding a New Module
|
|
399
|
+
|
|
400
|
+
To add a new feature module (e.g., "dashboard"), follow these steps:
|
|
401
|
+
|
|
402
|
+
### 1. Create Module Directory Structure
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
src/modules/dashboard/
|
|
406
|
+
├── components/
|
|
407
|
+
│ └── dashboard-widget.tsx
|
|
408
|
+
├── hooks/
|
|
409
|
+
│ └── use-dashboard-data.ts
|
|
410
|
+
├── layouts/
|
|
411
|
+
│ └── dashboard-layout.tsx
|
|
412
|
+
└── locales/
|
|
413
|
+
├── dashboard-en.json
|
|
414
|
+
└── dashboard-ja.json
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 2. Create Translation Files
|
|
418
|
+
|
|
419
|
+
**`src/modules/dashboard/locales/dashboard-en.json`**:
|
|
420
|
+
|
|
421
|
+
```json
|
|
422
|
+
{
|
|
423
|
+
"title": "Dashboard",
|
|
424
|
+
"welcome": "Welcome to Dashboard",
|
|
425
|
+
"widget": {
|
|
426
|
+
"title": "Widget",
|
|
427
|
+
"description": "Widget description"
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**`src/modules/dashboard/locales/dashboard-ja.json`**:
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{
|
|
436
|
+
"title": "ダッシュボード",
|
|
437
|
+
"welcome": "ダッシュボードへようこそ",
|
|
438
|
+
"widget": {
|
|
439
|
+
"title": "ウィジェット",
|
|
440
|
+
"description": "ウィジェットの説明"
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### 3. Update Global Locale Index
|
|
446
|
+
|
|
447
|
+
Add module translations to `src/locales/index.ts`:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
import enDashboard from '@/modules/dashboard/locales/dashboard-en.json';
|
|
451
|
+
import jaDashboard from '@/modules/dashboard/locales/dashboard-ja.json';
|
|
452
|
+
|
|
453
|
+
export const mergeTranslations = (lang: SupportedLanguages) => {
|
|
454
|
+
if (lang === 'en') {
|
|
455
|
+
return {
|
|
456
|
+
// ... existing modules
|
|
457
|
+
dashboard: { ...enDashboard },
|
|
458
|
+
};
|
|
459
|
+
} else {
|
|
460
|
+
return {
|
|
461
|
+
// ... existing modules
|
|
462
|
+
dashboard: { ...jaDashboard },
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 4. Create Layout Component
|
|
469
|
+
|
|
470
|
+
**`src/modules/dashboard/layouts/dashboard-layout.tsx`**:
|
|
471
|
+
|
|
472
|
+
```tsx
|
|
473
|
+
export function DashboardLayout({ children }: { children: React.ReactNode }) {
|
|
474
|
+
return (
|
|
475
|
+
<div className='dashboard-container'>
|
|
476
|
+
{/* Dashboard-specific layout */}
|
|
477
|
+
{children}
|
|
478
|
+
</div>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### 5. Create Route Files
|
|
484
|
+
|
|
485
|
+
**`src/routes/dashboard/route.tsx`**:
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
import { createFileRoute, Outlet } from '@tanstack/react-router';
|
|
489
|
+
import { DashboardLayout } from '@/modules/dashboard/layouts/dashboard-layout';
|
|
490
|
+
|
|
491
|
+
export const Route = createFileRoute('/dashboard')({
|
|
492
|
+
component: RouteComponent,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
function RouteComponent() {
|
|
496
|
+
return (
|
|
497
|
+
<DashboardLayout>
|
|
498
|
+
<Outlet />
|
|
499
|
+
</DashboardLayout>
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**`src/routes/dashboard/index.tsx`**:
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
508
|
+
import { DashboardPage } from '@/modules/dashboard/components/dashboard-page';
|
|
509
|
+
|
|
510
|
+
export const Route = createFileRoute('/dashboard/')({
|
|
511
|
+
component: RouteComponent,
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
function RouteComponent() {
|
|
515
|
+
return <DashboardPage />;
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### 6. Update Generator (if using Yeoman generator)
|
|
520
|
+
|
|
521
|
+
If you're maintaining the generator, add the new module files to `generator-kodly-react-app/generators/app/index.js`:
|
|
522
|
+
|
|
523
|
+
```javascript
|
|
524
|
+
_writeDashboardFiles() {
|
|
525
|
+
const dashboardFiles = [
|
|
526
|
+
'src/modules/dashboard/components/dashboard-page.tsx',
|
|
527
|
+
'src/modules/dashboard/layouts/dashboard-layout.tsx',
|
|
528
|
+
'src/modules/dashboard/locales/dashboard-en.json',
|
|
529
|
+
'src/modules/dashboard/locales/dashboard-ja.json',
|
|
530
|
+
'src/routes/dashboard/route.tsx',
|
|
531
|
+
'src/routes/dashboard/index.tsx',
|
|
532
|
+
];
|
|
533
|
+
dashboardFiles.forEach((file) => this._writeFile(file));
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
## Naming Conventions
|
|
538
|
+
|
|
539
|
+
### Files and Directories
|
|
540
|
+
|
|
541
|
+
- **Directories**: kebab-case (e.g., `user-profile/`, `auth-flow/`)
|
|
542
|
+
- **Component files**: kebab-case (e.g., `login-form.tsx`, `user-card.tsx`)
|
|
543
|
+
- **Hook files**: kebab-case with `use-` prefix (e.g., `use-auth-hook.ts`)
|
|
544
|
+
- **Utility files**: kebab-case (e.g., `error-handler.ts`, `api-client.ts`)
|
|
545
|
+
- **Route files**: kebab-case (e.g., `login.tsx`, `user-profile.tsx`)
|
|
546
|
+
|
|
547
|
+
### Code Elements
|
|
548
|
+
|
|
549
|
+
- **Components**: PascalCase (e.g., `LoginForm`, `UserCard`)
|
|
550
|
+
- **Hooks**: camelCase with `use` prefix (e.g., `useAuth`, `useUserData`)
|
|
551
|
+
- **Functions**: camelCase (e.g., `handleSubmit`, `validateEmail`)
|
|
552
|
+
- **Constants**: UPPER_SNAKE_CASE (e.g., `DEFAULT_ROUTE`, `API_BASE_URL`)
|
|
553
|
+
- **Types/Interfaces**: PascalCase (e.g., `User`, `AuthContext`)
|
|
554
|
+
|
|
555
|
+
### Module Names
|
|
556
|
+
|
|
557
|
+
- Use singular nouns (e.g., `auth`, `user`, `dashboard`)
|
|
558
|
+
- Keep names concise and descriptive
|
|
559
|
+
- Avoid abbreviations unless widely understood
|
|
560
|
+
|
|
561
|
+
## File Patterns
|
|
562
|
+
|
|
563
|
+
### Component File Pattern
|
|
564
|
+
|
|
565
|
+
```tsx
|
|
566
|
+
// src/modules/{module}/components/{component-name}.tsx
|
|
567
|
+
import { useTranslation } from 'react-i18next';
|
|
568
|
+
|
|
569
|
+
export function ComponentName() {
|
|
570
|
+
const { t } = useTranslation();
|
|
571
|
+
|
|
572
|
+
return <div>{/* Component JSX */}</div>;
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Hook File Pattern
|
|
577
|
+
|
|
578
|
+
```tsx
|
|
579
|
+
// src/modules/{module}/hooks/use-{hook-name}.ts
|
|
580
|
+
import { useAtom } from 'jotai';
|
|
581
|
+
|
|
582
|
+
export function useHookName() {
|
|
583
|
+
// Hook logic
|
|
584
|
+
return {
|
|
585
|
+
// Return values
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### Layout File Pattern
|
|
591
|
+
|
|
592
|
+
```tsx
|
|
593
|
+
// src/modules/{module}/layouts/{module}-layout.tsx
|
|
594
|
+
export function ModuleLayout({ children }: { children: React.ReactNode }) {
|
|
595
|
+
return (
|
|
596
|
+
<div className='module-container'>
|
|
597
|
+
{/* Layout structure */}
|
|
598
|
+
{children}
|
|
599
|
+
</div>
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Route File Pattern
|
|
605
|
+
|
|
606
|
+
```tsx
|
|
607
|
+
// src/routes/{module}/{page}.tsx
|
|
608
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
609
|
+
import { ComponentName } from '@/modules/{module}/components/component-name';
|
|
610
|
+
|
|
611
|
+
export const Route = createFileRoute('/{module}/{page}')({
|
|
612
|
+
component: RouteComponent,
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
function RouteComponent() {
|
|
616
|
+
return <ComponentName />;
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Translation File Pattern
|
|
621
|
+
|
|
622
|
+
```json
|
|
623
|
+
// src/modules/{module}/locales/{module}-{lang}.json
|
|
624
|
+
{
|
|
625
|
+
"section": {
|
|
626
|
+
"key": "Translation value",
|
|
627
|
+
"nested": {
|
|
628
|
+
"key": "Nested translation"
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
## Best Practices
|
|
635
|
+
|
|
636
|
+
1. **Keep modules self-contained**: Module components should primarily import from within their module or shared locations
|
|
637
|
+
2. **Use shared components**: Place reusable UI components in `src/components/ui/`
|
|
638
|
+
3. **Follow the translation pattern**: Always add translations for new modules and update `locales/index.ts`
|
|
639
|
+
4. **Route organization**: Group related routes under a parent route with a layout
|
|
640
|
+
5. **Type safety**: Use TypeScript types consistently and leverage the generated SDK types
|
|
641
|
+
6. **Consistent naming**: Follow the naming conventions outlined above
|
|
642
|
+
7. **Separation of concerns**: Keep business logic in hooks, UI in components, state in contexts/atoms
|
|
643
|
+
|
|
644
|
+
## Summary
|
|
645
|
+
|
|
646
|
+
This template follows a **feature-based modular architecture** where:
|
|
647
|
+
|
|
648
|
+
- **Modules** (`src/modules/`) contain feature-specific code (components, hooks, layouts, translations)
|
|
649
|
+
- **Routes** (`src/routes/`) map URL paths to components using TanStack Router
|
|
650
|
+
- **Shared components** (`src/components/`) provide reusable UI primitives
|
|
651
|
+
- **Library code** (`src/lib/`) contains utilities, API clients, and shared logic
|
|
652
|
+
- **Translations** are organized at both global and module levels
|
|
653
|
+
- Each module is **self-contained** with its own components, layouts, hooks, and translations
|
|
654
|
+
|
|
655
|
+
When adding new features:
|
|
656
|
+
|
|
657
|
+
1. Create a new module directory under `src/modules/`
|
|
658
|
+
2. Add module-specific components, hooks, layouts, and translations
|
|
659
|
+
3. Create corresponding route files in `src/routes/`
|
|
660
|
+
4. Update the global locale index to include module translations
|
|
661
|
+
5. Follow the established naming conventions and file patterns
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "tailwind.config.js",
|
|
8
|
+
"css": "src/index.css",
|
|
9
|
+
"baseColor": "stone",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
14
|
+
"aliases": {
|
|
15
|
+
"components": "@/components",
|
|
16
|
+
"utils": "@/lib/utils",
|
|
17
|
+
"ui": "@/components/ui",
|
|
18
|
+
"lib": "@/lib",
|
|
19
|
+
"hooks": "@/hooks"
|
|
20
|
+
},
|
|
21
|
+
"registries": {}
|
|
22
|
+
}
|
|
@@ -4,15 +4,23 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta
|
|
6
6
|
name="viewport"
|
|
7
|
-
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
8
|
+
<meta
|
|
9
|
+
name="theme-color"
|
|
10
|
+
content="#000000" />
|
|
11
|
+
<meta
|
|
12
|
+
name="description"
|
|
13
|
+
content="<%= appNameTitleCase %>" />
|
|
14
|
+
<link
|
|
15
|
+
rel="icon"
|
|
16
|
+
type="image/svg+xml"
|
|
17
|
+
href="/favicon.svg" />
|
|
11
18
|
<title><%= appNameTitleCase %></title>
|
|
12
19
|
</head>
|
|
13
20
|
<body>
|
|
14
21
|
<div id="app"></div>
|
|
15
|
-
<script
|
|
22
|
+
<script
|
|
23
|
+
type="module"
|
|
24
|
+
src="/src/main.tsx"></script>
|
|
16
25
|
</body>
|
|
17
26
|
</html>
|
|
18
|
-
|