create-reactivite 1.1.0 → 1.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/README.md +198 -197
- package/index.js +26 -1
- package/package.json +4 -3
- package/template/_gitignore +24 -0
- package/template2/.env.example +8 -0
- package/template2/.husky/pre-commit +4 -0
- package/template2/.prettierrc +5 -0
- package/template2/README.md +73 -0
- package/template2/__tests__/example.test.ts +20 -0
- package/template2/_gitignore +37 -0
- package/template2/app/[locale]/(private)/dashboard/page.tsx +52 -0
- package/template2/app/[locale]/(public)/login/page.tsx +83 -0
- package/template2/app/[locale]/layout.tsx +56 -0
- package/template2/app/[locale]/locales.ts +10 -0
- package/template2/app/[locale]/page.tsx +38 -0
- package/template2/app/api/clear-session/route.ts +10 -0
- package/template2/app/globals.css +127 -0
- package/template2/app/layout.tsx +7 -0
- package/template2/app/page.tsx +6 -0
- package/template2/components/AuthEventListener.tsx +22 -0
- package/template2/components/theme-provider.tsx +78 -0
- package/template2/components/ui/button.tsx +60 -0
- package/template2/components/ui/card.tsx +92 -0
- package/template2/components/ui/input.tsx +21 -0
- package/template2/components/ui/label.tsx +24 -0
- package/template2/components/ui/sonner.tsx +40 -0
- package/template2/components.json +22 -0
- package/template2/config/constants.ts +7 -0
- package/template2/config/env.ts +5 -0
- package/template2/contexts/translation-context.tsx +70 -0
- package/template2/eslint.config.mjs +18 -0
- package/template2/hoc/provider.tsx +27 -0
- package/template2/lib/paramsSerializer.ts +40 -0
- package/template2/lib/utils.ts +6 -0
- package/template2/locales/az.json +20 -0
- package/template2/locales/en.json +20 -0
- package/template2/next-env.d.ts +6 -0
- package/template2/next.config.ts +17 -0
- package/template2/orval.config.ts +66 -0
- package/template2/package.json +62 -0
- package/template2/pnpm-lock.yaml +6804 -0
- package/template2/postcss.config.mjs +7 -0
- package/template2/public/.gitkeep +0 -0
- package/template2/scripts/fix-generated-types.mjs +13 -0
- package/template2/services/generated/.gitkeep +2 -0
- package/template2/services/httpClient/httpClient.ts +70 -0
- package/template2/services/httpClient/orvalMutator.ts +10 -0
- package/template2/store/example-store.tsx +16 -0
- package/template2/store/user-store.tsx +29 -0
- package/template2/testing/msw/handlers/index.ts +6 -0
- package/template2/testing/msw/server.ts +4 -0
- package/template2/tsconfig.json +34 -0
- package/template2/tsconfig.tsbuildinfo +1 -0
- package/template2/vitest.config.ts +17 -0
- package/template2/vitest.setup.ts +7 -0
package/README.md
CHANGED
|
@@ -1,197 +1,198 @@
|
|
|
1
|
-
# create-reactivite
|
|
2
|
-
|
|
3
|
-
A modern
|
|
4
|
-
|
|
5
|
-
## 🚀
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- **
|
|
61
|
-
- **
|
|
62
|
-
- **
|
|
63
|
-
- **
|
|
64
|
-
- **
|
|
65
|
-
|
|
66
|
-
###
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
my-app/
|
|
77
|
-
├── public/
|
|
78
|
-
|
|
79
|
-
├──
|
|
80
|
-
│ ├──
|
|
81
|
-
│ ├── components/
|
|
82
|
-
│ │
|
|
83
|
-
│
|
|
84
|
-
│
|
|
85
|
-
│ ├──
|
|
86
|
-
│ │ └──
|
|
87
|
-
│ ├──
|
|
88
|
-
│
|
|
89
|
-
│
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
##
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
##
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
- [React
|
|
192
|
-
- [
|
|
193
|
-
- [
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
1
|
+
# create-reactivite
|
|
2
|
+
|
|
3
|
+
A modern frontend boilerplate generator. On run it asks which template you want, then scaffolds a production-ready app with TypeScript, Tailwind CSS v4 and shadcn/ui pre-wired.
|
|
4
|
+
|
|
5
|
+
## 🚀 Templates
|
|
6
|
+
|
|
7
|
+
When you run the CLI you pick one of two templates:
|
|
8
|
+
|
|
9
|
+
| Template | Stack |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| **React + Vite** | React 19, Vite 8 (Rolldown), Tailwind v4, shadcn/ui, React Router v7, Recharts |
|
|
12
|
+
| **Next.js 16** | Next.js 16 (App Router), React 19, Tailwind v4, shadcn/ui, i18n, TanStack Query, axios + orval, Zustand, react-hook-form + zod, husky, Vitest + MSW |
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
$ npx create-reactivite my-app
|
|
16
|
+
|
|
17
|
+
? Project name: my-app
|
|
18
|
+
? Pick a template: ›
|
|
19
|
+
❯ React + Vite (Tailwind v4, shadcn/ui, React Router)
|
|
20
|
+
Next.js 16 (App Router, i18n, TanStack Query, orval, Zustand, husky)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 📦 Installation
|
|
24
|
+
|
|
25
|
+
### Using npx (Recommended)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx create-reactivite my-app
|
|
29
|
+
cd my-app
|
|
30
|
+
pnpm dev
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Using npm
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm create reactivite my-app
|
|
37
|
+
cd my-app
|
|
38
|
+
npm run dev
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Install in current directory
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx create-reactivite .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Dependencies install automatically (`pnpm`, falling back to `npm`).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## ⚛️ Template 1 — React + Vite
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
- **⚡ Vite 8** — Lightning-fast build tool and dev server (Rolldown bundler)
|
|
56
|
+
- **⚛️ React 19** — Latest React with modern features
|
|
57
|
+
- **📘 TypeScript 6** — Full TypeScript with strict configuration
|
|
58
|
+
- **🎨 Tailwind CSS v4** — Config-less, CSS-variable driven theme
|
|
59
|
+
- **🧩 shadcn/ui** — Beautiful, accessible UI components (new-york)
|
|
60
|
+
- **🧭 React Router v7** — Client-side routing with `createBrowserRouter`
|
|
61
|
+
- **📊 Recharts** — Composable charts for the admin dashboard
|
|
62
|
+
- **🌙 Dark Mode** — Built-in theme switching
|
|
63
|
+
- **🔔 Toasts** — Sonner notifications
|
|
64
|
+
- **🎯 ESLint** — Modern flat config
|
|
65
|
+
|
|
66
|
+
### Scripts
|
|
67
|
+
|
|
68
|
+
- `pnpm dev` — dev server (port 5173)
|
|
69
|
+
- `pnpm build` — `tsc -b && vite build`
|
|
70
|
+
- `pnpm preview` — serve the production build
|
|
71
|
+
- `pnpm lint` — ESLint
|
|
72
|
+
|
|
73
|
+
### Structure
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
my-app/
|
|
77
|
+
├── public/
|
|
78
|
+
├── src/
|
|
79
|
+
│ ├── components/
|
|
80
|
+
│ │ ├── ui/ # shadcn/ui components
|
|
81
|
+
│ │ ├── home-page-components/
|
|
82
|
+
│ │ └── admin-page-components/
|
|
83
|
+
│ ├── lib/utils.ts
|
|
84
|
+
│ ├── pages/
|
|
85
|
+
│ │ ├── Homepage/
|
|
86
|
+
│ │ └── Dashboard/
|
|
87
|
+
│ ├── App.tsx # createBrowserRouter route shell
|
|
88
|
+
│ ├── main.tsx
|
|
89
|
+
│ └── global.css
|
|
90
|
+
├── components.json
|
|
91
|
+
├── vite.config.ts
|
|
92
|
+
└── eslint.config.js
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Routing
|
|
96
|
+
|
|
97
|
+
Routes live in `App.tsx` via `createBrowserRouter` from **react-router** v7 (not `react-router-dom`):
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { createBrowserRouter } from "react-router"
|
|
101
|
+
|
|
102
|
+
const router = createBrowserRouter([
|
|
103
|
+
{ path: "/", element: <Homepage /> },
|
|
104
|
+
{ path: "/dashboard", element: <Dashboard /> },
|
|
105
|
+
])
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## ▲ Template 2 — Next.js 16
|
|
111
|
+
|
|
112
|
+
A locale-scoped App Router boilerplate with a full data layer and tooling.
|
|
113
|
+
|
|
114
|
+
### Features
|
|
115
|
+
|
|
116
|
+
- **▲ Next.js 16** — App Router, `output: "standalone"`
|
|
117
|
+
- **🌍 i18n** — `app/[locale]` routing, lightweight `TranslationProvider` + `locales/*.json`
|
|
118
|
+
- **🔁 TanStack Query** — `QueryClientProvider` + Devtools
|
|
119
|
+
- **🔌 axios + orval** — typed API hooks generated from your OpenAPI schema
|
|
120
|
+
- **🐻 Zustand** — state stores (persisted `user-store`)
|
|
121
|
+
- **📝 react-hook-form + zod** — typed forms
|
|
122
|
+
- **🧪 Vitest + MSW** — unit tests with mocked network
|
|
123
|
+
- **🐶 husky** — pre-commit: lint + format + tests
|
|
124
|
+
- **🎨 Tailwind v4 + shadcn/ui**
|
|
125
|
+
|
|
126
|
+
### Scripts
|
|
127
|
+
|
|
128
|
+
- `pnpm dev` — dev server (port 3000, redirects `/` → `/az`)
|
|
129
|
+
- `pnpm build` — `next build`
|
|
130
|
+
- `pnpm test` / `pnpm test:run` — Vitest
|
|
131
|
+
- `pnpm generate:api` — orval codegen into `services/generated/`
|
|
132
|
+
- `pnpm lint` / `pnpm format`
|
|
133
|
+
|
|
134
|
+
### Structure
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
my-app/
|
|
138
|
+
├── app/
|
|
139
|
+
│ ├── layout.tsx # root passthrough
|
|
140
|
+
│ ├── page.tsx # redirects to /{DEFAULT_LOCALE}
|
|
141
|
+
│ ├── globals.css
|
|
142
|
+
│ ├── api/clear-session/
|
|
143
|
+
│ └── [locale]/
|
|
144
|
+
│ ├── layout.tsx # html/body shell + providers
|
|
145
|
+
│ ├── locales.ts # server-only dictionary loader
|
|
146
|
+
│ ├── page.tsx # Home
|
|
147
|
+
│ ├── (public)/login/
|
|
148
|
+
│ └── (private)/dashboard/
|
|
149
|
+
├── components/ui/ # shadcn/ui
|
|
150
|
+
├── config/ # env + constants (LOCALES)
|
|
151
|
+
├── contexts/ # translation-context
|
|
152
|
+
├── hoc/ # QueryProvider
|
|
153
|
+
├── lib/ # utils, paramsSerializer
|
|
154
|
+
├── services/
|
|
155
|
+
│ ├── httpClient/ # axios + orval mutator
|
|
156
|
+
│ └── generated/ # orval output
|
|
157
|
+
├── store/ # zustand
|
|
158
|
+
├── locales/ # az.json, en.json
|
|
159
|
+
├── testing/msw/
|
|
160
|
+
└── orval.config.ts
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### API codegen (orval)
|
|
164
|
+
|
|
165
|
+
1. Point `orval.config.ts` `input.target` at your OpenAPI schema (or set `OPENAPI_TARGET`).
|
|
166
|
+
2. `pnpm generate:api` → writes react-query hooks + models to `services/generated/`.
|
|
167
|
+
|
|
168
|
+
> The `@/` path alias maps to the **project root** in this template (not `src/`).
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🎨 Adding shadcn/ui Components
|
|
173
|
+
|
|
174
|
+
Both templates use shadcn/ui (new-york, lucide icons):
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx shadcn@latest add button
|
|
178
|
+
npx shadcn@latest add form
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## 🤝 Contributing
|
|
182
|
+
|
|
183
|
+
Contributions welcome — open a PR.
|
|
184
|
+
|
|
185
|
+
## 📄 License
|
|
186
|
+
|
|
187
|
+
MIT
|
|
188
|
+
|
|
189
|
+
## 🔗 Links
|
|
190
|
+
|
|
191
|
+
- [React](https://react.dev/) · [Next.js](https://nextjs.org/) · [Vite](https://vite.dev/)
|
|
192
|
+
- [Tailwind CSS](https://tailwindcss.com/) · [shadcn/ui](https://ui.shadcn.com/)
|
|
193
|
+
- [React Router](https://reactrouter.com/) · [TanStack Query](https://tanstack.com/query) · [orval](https://orval.dev/)
|
|
194
|
+
- [Zustand](https://zustand.docs.pmnd.rs/) · [Recharts](https://recharts.org/) · [TypeScript](https://www.typescriptlang.org/)
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
**Happy coding! 🎉**
|
package/index.js
CHANGED
|
@@ -18,13 +18,38 @@ const __dirname = path.dirname(__filename);
|
|
|
18
18
|
initial: "my-react-app",
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
// 🧩 0. Hansı template istifadə olunacaq — istifadəçi seçir
|
|
22
|
+
const { template } = await prompts({
|
|
23
|
+
type: "select",
|
|
24
|
+
name: "template",
|
|
25
|
+
message: "Pick a template:",
|
|
26
|
+
choices: [
|
|
27
|
+
{
|
|
28
|
+
title: "React + Vite (Tailwind v4, shadcn/ui, React Router)",
|
|
29
|
+
value: "template",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title:
|
|
33
|
+
"Next.js 16 (App Router, i18n, TanStack Query, orval, Zustand, husky)",
|
|
34
|
+
value: "template2",
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
initial: 0,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// İstifadəçi seçimi ləğv etdisə (Ctrl+C) — çıx
|
|
41
|
+
if (!template) {
|
|
42
|
+
console.log("❌ Operation cancelled.");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
21
46
|
// 🧩 1. Target folderı müəyyən edirik
|
|
22
47
|
const isCurrentDir = projectName === "." || projectName === "./";
|
|
23
48
|
const targetPath = isCurrentDir
|
|
24
49
|
? process.cwd()
|
|
25
50
|
: path.resolve(process.cwd(), projectName);
|
|
26
51
|
|
|
27
|
-
const templatePath = path.resolve(__dirname,
|
|
52
|
+
const templatePath = path.resolve(__dirname, template);
|
|
28
53
|
|
|
29
54
|
// 🧩 2. Əgər current folderdirsə — içi boşdursa davam et, yoxsa xəbərdarlıq ver
|
|
30
55
|
if (isCurrentDir) {
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-reactivite",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "⚡
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "⚡ Scaffold modern frontend projects in seconds — pick a template: React + Vite or Next.js 16 (App Router). Both ship Tailwind v4, shadcn/ui, TypeScript and a clean, production-ready structure. The Next.js template adds i18n, TanStack Query, axios/orval, Zustand, husky and Vitest. Zero setup hassle.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-reactivite": "./index.js"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"files": [
|
|
10
10
|
"index.js",
|
|
11
|
-
"template/"
|
|
11
|
+
"template/",
|
|
12
|
+
"template2/"
|
|
12
13
|
],
|
|
13
14
|
"dependencies": {
|
|
14
15
|
"prompts": "^2.4.2",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
pnpm-debug.log*
|
|
8
|
+
lerna-debug.log*
|
|
9
|
+
|
|
10
|
+
node_modules
|
|
11
|
+
dist
|
|
12
|
+
dist-ssr
|
|
13
|
+
*.local
|
|
14
|
+
|
|
15
|
+
# Editor directories and files
|
|
16
|
+
.vscode/*
|
|
17
|
+
!.vscode/extensions.json
|
|
18
|
+
.idea
|
|
19
|
+
.DS_Store
|
|
20
|
+
*.suo
|
|
21
|
+
*.ntvs*
|
|
22
|
+
*.njsproj
|
|
23
|
+
*.sln
|
|
24
|
+
*.sw?
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Public API base URL used by the browser (axios httpClient).
|
|
2
|
+
NEXT_PUBLIC_API_BASE_URL=/api/backend
|
|
3
|
+
|
|
4
|
+
# Server-side backend URL proxied via next.config.ts rewrites.
|
|
5
|
+
API_BASE_URL=http://localhost:8080/api
|
|
6
|
+
|
|
7
|
+
# OpenAPI schema used by orval (npm run generate:api).
|
|
8
|
+
OPENAPI_TARGET=http://localhost:8080/v3/api-docs
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Nextivite
|
|
2
|
+
|
|
3
|
+
Next.js 16 (App Router) boilerplate scaffolded by **create-reactivite**.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
- **Next.js 16** + React 19 (App Router, `output: "standalone"`)
|
|
8
|
+
- **Tailwind CSS v4** (`@tailwindcss/postcss`, config-less) + shadcn/ui (new-york)
|
|
9
|
+
- **i18n** — `app/[locale]` routing with a lightweight `TranslationProvider` + `locales/*.json`
|
|
10
|
+
- **TanStack Query** (+ Devtools) via `hoc/provider.tsx`
|
|
11
|
+
- **axios** httpClient with interceptors + **orval** for type-safe API hooks
|
|
12
|
+
- **Zustand** stores (`store/`)
|
|
13
|
+
- **react-hook-form** + **zod** forms
|
|
14
|
+
- **Vitest** + **MSW** + Testing Library
|
|
15
|
+
- **husky** pre-commit (lint + format + tests), **prettier**, **eslint-config-next**
|
|
16
|
+
|
|
17
|
+
## Getting started
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm install # or npm install
|
|
21
|
+
pnpm dev # http://localhost:3000 → redirects to /az
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
app/
|
|
28
|
+
layout.tsx # root passthrough
|
|
29
|
+
page.tsx # redirects to /{DEFAULT_LOCALE}
|
|
30
|
+
globals.css # Tailwind v4 theme tokens
|
|
31
|
+
api/clear-session/ # cookie-clearing route
|
|
32
|
+
[locale]/
|
|
33
|
+
layout.tsx # html/body shell + all providers
|
|
34
|
+
locales.ts # server-only dictionary loader
|
|
35
|
+
page.tsx # Home
|
|
36
|
+
(public)/login/ # login (react-hook-form + zod)
|
|
37
|
+
(private)/dashboard/ # guarded page
|
|
38
|
+
components/
|
|
39
|
+
ui/ # shadcn/ui components
|
|
40
|
+
theme-provider.tsx
|
|
41
|
+
AuthEventListener.tsx
|
|
42
|
+
config/ # env + constants (LOCALES, timeouts)
|
|
43
|
+
contexts/ # translation-context
|
|
44
|
+
hoc/ # QueryProvider
|
|
45
|
+
lib/ # utils, paramsSerializer
|
|
46
|
+
services/
|
|
47
|
+
httpClient/ # axios instance + orval mutator
|
|
48
|
+
generated/ # orval output (git-ignored content)
|
|
49
|
+
store/ # zustand stores
|
|
50
|
+
locales/ # az.json, en.json
|
|
51
|
+
testing/msw/ # mock server + handlers
|
|
52
|
+
__tests__/ # vitest specs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API codegen (orval)
|
|
56
|
+
|
|
57
|
+
1. Point `orval.config.ts` `input.target` at your OpenAPI schema (or set `OPENAPI_TARGET`).
|
|
58
|
+
2. `pnpm generate:api` → writes react-query hooks + models to `services/generated/`.
|
|
59
|
+
|
|
60
|
+
## Scripts
|
|
61
|
+
|
|
62
|
+
- `pnpm dev` / `pnpm build` / `pnpm start`
|
|
63
|
+
- `pnpm lint` / `pnpm format`
|
|
64
|
+
- `pnpm test` / `pnpm test:run`
|
|
65
|
+
- `pnpm generate` / `pnpm generate:api`
|
|
66
|
+
|
|
67
|
+
## Adding components
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx shadcn@latest add <name>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`components.json` points `css` at `app/globals.css`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { paramsSerializer } from '@/lib/paramsSerializer';
|
|
3
|
+
|
|
4
|
+
describe('paramsSerializer', () => {
|
|
5
|
+
it('flattens nested objects', () => {
|
|
6
|
+
expect(paramsSerializer({ pageable: { page: 0, size: 10 } })).toBe(
|
|
7
|
+
'page=0&size=10',
|
|
8
|
+
);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('repeats array values', () => {
|
|
12
|
+
expect(paramsSerializer({ sort: ['name,asc', 'id,desc'] })).toBe(
|
|
13
|
+
'sort=name%2Casc&sort=id%2Cdesc',
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('omits null and undefined', () => {
|
|
18
|
+
expect(paramsSerializer({ a: 1, b: null, c: undefined })).toBe('a=1');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
.yarn/*
|
|
8
|
+
|
|
9
|
+
# testing
|
|
10
|
+
/coverage
|
|
11
|
+
|
|
12
|
+
# next.js
|
|
13
|
+
/.next/
|
|
14
|
+
/out/
|
|
15
|
+
|
|
16
|
+
# production
|
|
17
|
+
/build
|
|
18
|
+
|
|
19
|
+
# misc
|
|
20
|
+
.DS_Store
|
|
21
|
+
*.pem
|
|
22
|
+
|
|
23
|
+
# debug
|
|
24
|
+
npm-debug.log*
|
|
25
|
+
yarn-debug.log*
|
|
26
|
+
yarn-error.log*
|
|
27
|
+
.pnpm-debug.log*
|
|
28
|
+
|
|
29
|
+
# env files (can opt-in for committing if needed)
|
|
30
|
+
.env*
|
|
31
|
+
|
|
32
|
+
# vercel
|
|
33
|
+
.vercel
|
|
34
|
+
|
|
35
|
+
# typescript
|
|
36
|
+
*.tsbuildinfo
|
|
37
|
+
next-env.d.ts
|