ChristopherJKoen commited on
Commit
f48f5c4
·
1 Parent(s): bdfdb65

Industry Standard

Browse files
.gitignore CHANGED
@@ -2,6 +2,7 @@
2
  __pycache__/
3
  *.py[cod]
4
  .venv/
 
5
 
6
  # Node
7
  node_modules/
 
2
  __pycache__/
3
  *.py[cod]
4
  .venv/
5
+ .env
6
 
7
  # Node
8
  node_modules/
README.md CHANGED
@@ -1,8 +1,27 @@
1
- # Minimal Server + Web Starter
2
 
3
- This repository is a stripped-down template with:
4
- - `server/` - FastAPI API with a single `/health` endpoint.
5
- - `frontend/` - Vite + React app that renders a black full-screen page.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  ## Quick Start
8
 
@@ -22,3 +41,10 @@ npm run dev
22
  ```
23
 
24
  Open `http://localhost:5173`.
 
 
 
 
 
 
 
 
1
+ # Starter: FastAPI + Vite (Minimal)
2
 
3
+ A minimal, industry-standard starter with:
4
+ - `server/` - FastAPI API (`/api/health`).
5
+ - `frontend/` - Vite + React app that renders a full-screen black page.
6
+
7
+ ## Project Layout
8
+
9
+ ```
10
+ server/
11
+ app/
12
+ api/
13
+ routes/
14
+ health.py
15
+ router.py
16
+ core/
17
+ config.py
18
+ main.py
19
+ frontend/
20
+ src/
21
+ App.tsx
22
+ main.tsx
23
+ index.css
24
+ ```
25
 
26
  ## Quick Start
27
 
 
41
  ```
42
 
43
  Open `http://localhost:5173`.
44
+
45
+ ## Configuration
46
+
47
+ Environment variables for the API:
48
+ - `APP_NAME` (default: `Starter API`)
49
+ - `API_PREFIX` (default: `/api`)
50
+ - `CORS_ORIGINS` (comma-separated, default: `http://localhost:5173`)
frontend/package-lock.json ADDED
@@ -0,0 +1,1388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "rightcodes-frontend",
3
+ "version": "0.1.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "rightcodes-frontend",
9
+ "version": "0.1.0",
10
+ "dependencies": {
11
+ "react": "^18.3.1",
12
+ "react-dom": "^18.3.1"
13
+ },
14
+ "devDependencies": {
15
+ "@types/react": "^18.3.3",
16
+ "@types/react-dom": "^18.3.3",
17
+ "@vitejs/plugin-react": "^4.3.1",
18
+ "typescript": "^5.4.5",
19
+ "vite": "^7.3.1"
20
+ }
21
+ },
22
+ "node_modules/@babel/code-frame": {
23
+ "version": "7.27.1",
24
+ "dev": true,
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "@babel/helper-validator-identifier": "^7.27.1",
28
+ "js-tokens": "^4.0.0",
29
+ "picocolors": "^1.1.1"
30
+ },
31
+ "engines": {
32
+ "node": ">=6.9.0"
33
+ }
34
+ },
35
+ "node_modules/@babel/compat-data": {
36
+ "version": "7.28.4",
37
+ "dev": true,
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=6.9.0"
41
+ }
42
+ },
43
+ "node_modules/@babel/core": {
44
+ "version": "7.28.4",
45
+ "dev": true,
46
+ "license": "MIT",
47
+ "dependencies": {
48
+ "@babel/code-frame": "^7.27.1",
49
+ "@babel/generator": "^7.28.3",
50
+ "@babel/helper-compilation-targets": "^7.27.2",
51
+ "@babel/helper-module-transforms": "^7.28.3",
52
+ "@babel/helpers": "^7.28.4",
53
+ "@babel/parser": "^7.28.4",
54
+ "@babel/template": "^7.27.2",
55
+ "@babel/traverse": "^7.28.4",
56
+ "@babel/types": "^7.28.4",
57
+ "@jridgewell/remapping": "^2.3.5",
58
+ "convert-source-map": "^2.0.0",
59
+ "debug": "^4.1.0",
60
+ "gensync": "^1.0.0-beta.2",
61
+ "json5": "^2.2.3",
62
+ "semver": "^6.3.1"
63
+ },
64
+ "engines": {
65
+ "node": ">=6.9.0"
66
+ },
67
+ "funding": {
68
+ "type": "opencollective",
69
+ "url": "https://opencollective.com/babel"
70
+ }
71
+ },
72
+ "node_modules/@babel/generator": {
73
+ "version": "7.28.3",
74
+ "dev": true,
75
+ "license": "MIT",
76
+ "dependencies": {
77
+ "@babel/parser": "^7.28.3",
78
+ "@babel/types": "^7.28.2",
79
+ "@jridgewell/gen-mapping": "^0.3.12",
80
+ "@jridgewell/trace-mapping": "^0.3.28",
81
+ "jsesc": "^3.0.2"
82
+ },
83
+ "engines": {
84
+ "node": ">=6.9.0"
85
+ }
86
+ },
87
+ "node_modules/@babel/helper-compilation-targets": {
88
+ "version": "7.27.2",
89
+ "dev": true,
90
+ "license": "MIT",
91
+ "dependencies": {
92
+ "@babel/compat-data": "^7.27.2",
93
+ "@babel/helper-validator-option": "^7.27.1",
94
+ "browserslist": "^4.24.0",
95
+ "lru-cache": "^5.1.1",
96
+ "semver": "^6.3.1"
97
+ },
98
+ "engines": {
99
+ "node": ">=6.9.0"
100
+ }
101
+ },
102
+ "node_modules/@babel/helper-globals": {
103
+ "version": "7.28.0",
104
+ "dev": true,
105
+ "license": "MIT",
106
+ "engines": {
107
+ "node": ">=6.9.0"
108
+ }
109
+ },
110
+ "node_modules/@babel/helper-module-imports": {
111
+ "version": "7.27.1",
112
+ "dev": true,
113
+ "license": "MIT",
114
+ "dependencies": {
115
+ "@babel/traverse": "^7.27.1",
116
+ "@babel/types": "^7.27.1"
117
+ },
118
+ "engines": {
119
+ "node": ">=6.9.0"
120
+ }
121
+ },
122
+ "node_modules/@babel/helper-module-transforms": {
123
+ "version": "7.28.3",
124
+ "dev": true,
125
+ "license": "MIT",
126
+ "dependencies": {
127
+ "@babel/helper-module-imports": "^7.27.1",
128
+ "@babel/helper-validator-identifier": "^7.27.1",
129
+ "@babel/traverse": "^7.28.3"
130
+ },
131
+ "engines": {
132
+ "node": ">=6.9.0"
133
+ },
134
+ "peerDependencies": {
135
+ "@babel/core": "^7.0.0"
136
+ }
137
+ },
138
+ "node_modules/@babel/helper-plugin-utils": {
139
+ "version": "7.27.1",
140
+ "dev": true,
141
+ "license": "MIT",
142
+ "engines": {
143
+ "node": ">=6.9.0"
144
+ }
145
+ },
146
+ "node_modules/@babel/helper-string-parser": {
147
+ "version": "7.27.1",
148
+ "dev": true,
149
+ "license": "MIT",
150
+ "engines": {
151
+ "node": ">=6.9.0"
152
+ }
153
+ },
154
+ "node_modules/@babel/helper-validator-identifier": {
155
+ "version": "7.27.1",
156
+ "dev": true,
157
+ "license": "MIT",
158
+ "engines": {
159
+ "node": ">=6.9.0"
160
+ }
161
+ },
162
+ "node_modules/@babel/helper-validator-option": {
163
+ "version": "7.27.1",
164
+ "dev": true,
165
+ "license": "MIT",
166
+ "engines": {
167
+ "node": ">=6.9.0"
168
+ }
169
+ },
170
+ "node_modules/@babel/helpers": {
171
+ "version": "7.28.4",
172
+ "dev": true,
173
+ "license": "MIT",
174
+ "dependencies": {
175
+ "@babel/template": "^7.27.2",
176
+ "@babel/types": "^7.28.4"
177
+ },
178
+ "engines": {
179
+ "node": ">=6.9.0"
180
+ }
181
+ },
182
+ "node_modules/@babel/parser": {
183
+ "version": "7.28.4",
184
+ "dev": true,
185
+ "license": "MIT",
186
+ "dependencies": {
187
+ "@babel/types": "^7.28.4"
188
+ },
189
+ "bin": {
190
+ "parser": "bin/babel-parser.js"
191
+ },
192
+ "engines": {
193
+ "node": ">=6.0.0"
194
+ }
195
+ },
196
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
197
+ "version": "7.27.1",
198
+ "dev": true,
199
+ "license": "MIT",
200
+ "dependencies": {
201
+ "@babel/helper-plugin-utils": "^7.27.1"
202
+ },
203
+ "engines": {
204
+ "node": ">=6.9.0"
205
+ },
206
+ "peerDependencies": {
207
+ "@babel/core": "^7.0.0-0"
208
+ }
209
+ },
210
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
211
+ "version": "7.27.1",
212
+ "dev": true,
213
+ "license": "MIT",
214
+ "dependencies": {
215
+ "@babel/helper-plugin-utils": "^7.27.1"
216
+ },
217
+ "engines": {
218
+ "node": ">=6.9.0"
219
+ },
220
+ "peerDependencies": {
221
+ "@babel/core": "^7.0.0-0"
222
+ }
223
+ },
224
+ "node_modules/@babel/template": {
225
+ "version": "7.27.2",
226
+ "dev": true,
227
+ "license": "MIT",
228
+ "dependencies": {
229
+ "@babel/code-frame": "^7.27.1",
230
+ "@babel/parser": "^7.27.2",
231
+ "@babel/types": "^7.27.1"
232
+ },
233
+ "engines": {
234
+ "node": ">=6.9.0"
235
+ }
236
+ },
237
+ "node_modules/@babel/traverse": {
238
+ "version": "7.28.4",
239
+ "dev": true,
240
+ "license": "MIT",
241
+ "dependencies": {
242
+ "@babel/code-frame": "^7.27.1",
243
+ "@babel/generator": "^7.28.3",
244
+ "@babel/helper-globals": "^7.28.0",
245
+ "@babel/parser": "^7.28.4",
246
+ "@babel/template": "^7.27.2",
247
+ "@babel/types": "^7.28.4",
248
+ "debug": "^4.3.1"
249
+ },
250
+ "engines": {
251
+ "node": ">=6.9.0"
252
+ }
253
+ },
254
+ "node_modules/@babel/types": {
255
+ "version": "7.28.4",
256
+ "dev": true,
257
+ "license": "MIT",
258
+ "dependencies": {
259
+ "@babel/helper-string-parser": "^7.27.1",
260
+ "@babel/helper-validator-identifier": "^7.27.1"
261
+ },
262
+ "engines": {
263
+ "node": ">=6.9.0"
264
+ }
265
+ },
266
+ "node_modules/@esbuild/aix-ppc64": {
267
+ "version": "0.27.2",
268
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
269
+ "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
270
+ "cpu": [
271
+ "ppc64"
272
+ ],
273
+ "dev": true,
274
+ "license": "MIT",
275
+ "optional": true,
276
+ "os": [
277
+ "aix"
278
+ ],
279
+ "engines": {
280
+ "node": ">=18"
281
+ }
282
+ },
283
+ "node_modules/@esbuild/android-arm": {
284
+ "version": "0.27.2",
285
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
286
+ "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
287
+ "cpu": [
288
+ "arm"
289
+ ],
290
+ "dev": true,
291
+ "license": "MIT",
292
+ "optional": true,
293
+ "os": [
294
+ "android"
295
+ ],
296
+ "engines": {
297
+ "node": ">=18"
298
+ }
299
+ },
300
+ "node_modules/@esbuild/android-arm64": {
301
+ "version": "0.27.2",
302
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
303
+ "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
304
+ "cpu": [
305
+ "arm64"
306
+ ],
307
+ "dev": true,
308
+ "license": "MIT",
309
+ "optional": true,
310
+ "os": [
311
+ "android"
312
+ ],
313
+ "engines": {
314
+ "node": ">=18"
315
+ }
316
+ },
317
+ "node_modules/@esbuild/android-x64": {
318
+ "version": "0.27.2",
319
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
320
+ "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
321
+ "cpu": [
322
+ "x64"
323
+ ],
324
+ "dev": true,
325
+ "license": "MIT",
326
+ "optional": true,
327
+ "os": [
328
+ "android"
329
+ ],
330
+ "engines": {
331
+ "node": ">=18"
332
+ }
333
+ },
334
+ "node_modules/@esbuild/darwin-arm64": {
335
+ "version": "0.27.2",
336
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
337
+ "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
338
+ "cpu": [
339
+ "arm64"
340
+ ],
341
+ "dev": true,
342
+ "license": "MIT",
343
+ "optional": true,
344
+ "os": [
345
+ "darwin"
346
+ ],
347
+ "engines": {
348
+ "node": ">=18"
349
+ }
350
+ },
351
+ "node_modules/@esbuild/darwin-x64": {
352
+ "version": "0.27.2",
353
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
354
+ "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
355
+ "cpu": [
356
+ "x64"
357
+ ],
358
+ "dev": true,
359
+ "license": "MIT",
360
+ "optional": true,
361
+ "os": [
362
+ "darwin"
363
+ ],
364
+ "engines": {
365
+ "node": ">=18"
366
+ }
367
+ },
368
+ "node_modules/@esbuild/freebsd-arm64": {
369
+ "version": "0.27.2",
370
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
371
+ "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
372
+ "cpu": [
373
+ "arm64"
374
+ ],
375
+ "dev": true,
376
+ "license": "MIT",
377
+ "optional": true,
378
+ "os": [
379
+ "freebsd"
380
+ ],
381
+ "engines": {
382
+ "node": ">=18"
383
+ }
384
+ },
385
+ "node_modules/@esbuild/freebsd-x64": {
386
+ "version": "0.27.2",
387
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
388
+ "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
389
+ "cpu": [
390
+ "x64"
391
+ ],
392
+ "dev": true,
393
+ "license": "MIT",
394
+ "optional": true,
395
+ "os": [
396
+ "freebsd"
397
+ ],
398
+ "engines": {
399
+ "node": ">=18"
400
+ }
401
+ },
402
+ "node_modules/@esbuild/linux-arm": {
403
+ "version": "0.27.2",
404
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
405
+ "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
406
+ "cpu": [
407
+ "arm"
408
+ ],
409
+ "dev": true,
410
+ "license": "MIT",
411
+ "optional": true,
412
+ "os": [
413
+ "linux"
414
+ ],
415
+ "engines": {
416
+ "node": ">=18"
417
+ }
418
+ },
419
+ "node_modules/@esbuild/linux-arm64": {
420
+ "version": "0.27.2",
421
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
422
+ "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
423
+ "cpu": [
424
+ "arm64"
425
+ ],
426
+ "dev": true,
427
+ "license": "MIT",
428
+ "optional": true,
429
+ "os": [
430
+ "linux"
431
+ ],
432
+ "engines": {
433
+ "node": ">=18"
434
+ }
435
+ },
436
+ "node_modules/@esbuild/linux-ia32": {
437
+ "version": "0.27.2",
438
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
439
+ "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
440
+ "cpu": [
441
+ "ia32"
442
+ ],
443
+ "dev": true,
444
+ "license": "MIT",
445
+ "optional": true,
446
+ "os": [
447
+ "linux"
448
+ ],
449
+ "engines": {
450
+ "node": ">=18"
451
+ }
452
+ },
453
+ "node_modules/@esbuild/linux-loong64": {
454
+ "version": "0.27.2",
455
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
456
+ "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
457
+ "cpu": [
458
+ "loong64"
459
+ ],
460
+ "dev": true,
461
+ "license": "MIT",
462
+ "optional": true,
463
+ "os": [
464
+ "linux"
465
+ ],
466
+ "engines": {
467
+ "node": ">=18"
468
+ }
469
+ },
470
+ "node_modules/@esbuild/linux-mips64el": {
471
+ "version": "0.27.2",
472
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
473
+ "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
474
+ "cpu": [
475
+ "mips64el"
476
+ ],
477
+ "dev": true,
478
+ "license": "MIT",
479
+ "optional": true,
480
+ "os": [
481
+ "linux"
482
+ ],
483
+ "engines": {
484
+ "node": ">=18"
485
+ }
486
+ },
487
+ "node_modules/@esbuild/linux-ppc64": {
488
+ "version": "0.27.2",
489
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
490
+ "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
491
+ "cpu": [
492
+ "ppc64"
493
+ ],
494
+ "dev": true,
495
+ "license": "MIT",
496
+ "optional": true,
497
+ "os": [
498
+ "linux"
499
+ ],
500
+ "engines": {
501
+ "node": ">=18"
502
+ }
503
+ },
504
+ "node_modules/@esbuild/linux-riscv64": {
505
+ "version": "0.27.2",
506
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
507
+ "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
508
+ "cpu": [
509
+ "riscv64"
510
+ ],
511
+ "dev": true,
512
+ "license": "MIT",
513
+ "optional": true,
514
+ "os": [
515
+ "linux"
516
+ ],
517
+ "engines": {
518
+ "node": ">=18"
519
+ }
520
+ },
521
+ "node_modules/@esbuild/linux-s390x": {
522
+ "version": "0.27.2",
523
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
524
+ "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
525
+ "cpu": [
526
+ "s390x"
527
+ ],
528
+ "dev": true,
529
+ "license": "MIT",
530
+ "optional": true,
531
+ "os": [
532
+ "linux"
533
+ ],
534
+ "engines": {
535
+ "node": ">=18"
536
+ }
537
+ },
538
+ "node_modules/@esbuild/linux-x64": {
539
+ "version": "0.27.2",
540
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
541
+ "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
542
+ "cpu": [
543
+ "x64"
544
+ ],
545
+ "dev": true,
546
+ "license": "MIT",
547
+ "optional": true,
548
+ "os": [
549
+ "linux"
550
+ ],
551
+ "engines": {
552
+ "node": ">=18"
553
+ }
554
+ },
555
+ "node_modules/@esbuild/netbsd-arm64": {
556
+ "version": "0.27.2",
557
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
558
+ "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
559
+ "cpu": [
560
+ "arm64"
561
+ ],
562
+ "dev": true,
563
+ "license": "MIT",
564
+ "optional": true,
565
+ "os": [
566
+ "netbsd"
567
+ ],
568
+ "engines": {
569
+ "node": ">=18"
570
+ }
571
+ },
572
+ "node_modules/@esbuild/netbsd-x64": {
573
+ "version": "0.27.2",
574
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
575
+ "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
576
+ "cpu": [
577
+ "x64"
578
+ ],
579
+ "dev": true,
580
+ "license": "MIT",
581
+ "optional": true,
582
+ "os": [
583
+ "netbsd"
584
+ ],
585
+ "engines": {
586
+ "node": ">=18"
587
+ }
588
+ },
589
+ "node_modules/@esbuild/openbsd-arm64": {
590
+ "version": "0.27.2",
591
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
592
+ "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
593
+ "cpu": [
594
+ "arm64"
595
+ ],
596
+ "dev": true,
597
+ "license": "MIT",
598
+ "optional": true,
599
+ "os": [
600
+ "openbsd"
601
+ ],
602
+ "engines": {
603
+ "node": ">=18"
604
+ }
605
+ },
606
+ "node_modules/@esbuild/openbsd-x64": {
607
+ "version": "0.27.2",
608
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
609
+ "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
610
+ "cpu": [
611
+ "x64"
612
+ ],
613
+ "dev": true,
614
+ "license": "MIT",
615
+ "optional": true,
616
+ "os": [
617
+ "openbsd"
618
+ ],
619
+ "engines": {
620
+ "node": ">=18"
621
+ }
622
+ },
623
+ "node_modules/@esbuild/openharmony-arm64": {
624
+ "version": "0.27.2",
625
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
626
+ "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
627
+ "cpu": [
628
+ "arm64"
629
+ ],
630
+ "dev": true,
631
+ "license": "MIT",
632
+ "optional": true,
633
+ "os": [
634
+ "openharmony"
635
+ ],
636
+ "engines": {
637
+ "node": ">=18"
638
+ }
639
+ },
640
+ "node_modules/@esbuild/sunos-x64": {
641
+ "version": "0.27.2",
642
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
643
+ "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
644
+ "cpu": [
645
+ "x64"
646
+ ],
647
+ "dev": true,
648
+ "license": "MIT",
649
+ "optional": true,
650
+ "os": [
651
+ "sunos"
652
+ ],
653
+ "engines": {
654
+ "node": ">=18"
655
+ }
656
+ },
657
+ "node_modules/@esbuild/win32-arm64": {
658
+ "version": "0.27.2",
659
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
660
+ "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
661
+ "cpu": [
662
+ "arm64"
663
+ ],
664
+ "dev": true,
665
+ "license": "MIT",
666
+ "optional": true,
667
+ "os": [
668
+ "win32"
669
+ ],
670
+ "engines": {
671
+ "node": ">=18"
672
+ }
673
+ },
674
+ "node_modules/@esbuild/win32-ia32": {
675
+ "version": "0.27.2",
676
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
677
+ "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
678
+ "cpu": [
679
+ "ia32"
680
+ ],
681
+ "dev": true,
682
+ "license": "MIT",
683
+ "optional": true,
684
+ "os": [
685
+ "win32"
686
+ ],
687
+ "engines": {
688
+ "node": ">=18"
689
+ }
690
+ },
691
+ "node_modules/@esbuild/win32-x64": {
692
+ "version": "0.27.2",
693
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
694
+ "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
695
+ "cpu": [
696
+ "x64"
697
+ ],
698
+ "dev": true,
699
+ "license": "MIT",
700
+ "optional": true,
701
+ "os": [
702
+ "win32"
703
+ ],
704
+ "engines": {
705
+ "node": ">=18"
706
+ }
707
+ },
708
+ "node_modules/@jridgewell/gen-mapping": {
709
+ "version": "0.3.13",
710
+ "dev": true,
711
+ "license": "MIT",
712
+ "dependencies": {
713
+ "@jridgewell/sourcemap-codec": "^1.5.0",
714
+ "@jridgewell/trace-mapping": "^0.3.24"
715
+ }
716
+ },
717
+ "node_modules/@jridgewell/remapping": {
718
+ "version": "2.3.5",
719
+ "dev": true,
720
+ "license": "MIT",
721
+ "dependencies": {
722
+ "@jridgewell/gen-mapping": "^0.3.5",
723
+ "@jridgewell/trace-mapping": "^0.3.24"
724
+ }
725
+ },
726
+ "node_modules/@jridgewell/resolve-uri": {
727
+ "version": "3.1.2",
728
+ "dev": true,
729
+ "license": "MIT",
730
+ "engines": {
731
+ "node": ">=6.0.0"
732
+ }
733
+ },
734
+ "node_modules/@jridgewell/sourcemap-codec": {
735
+ "version": "1.5.5",
736
+ "dev": true,
737
+ "license": "MIT"
738
+ },
739
+ "node_modules/@jridgewell/trace-mapping": {
740
+ "version": "0.3.31",
741
+ "dev": true,
742
+ "license": "MIT",
743
+ "dependencies": {
744
+ "@jridgewell/resolve-uri": "^3.1.0",
745
+ "@jridgewell/sourcemap-codec": "^1.4.14"
746
+ }
747
+ },
748
+ "node_modules/@rolldown/pluginutils": {
749
+ "version": "1.0.0-beta.27",
750
+ "dev": true,
751
+ "license": "MIT"
752
+ },
753
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
754
+ "version": "4.52.4",
755
+ "cpu": [
756
+ "x64"
757
+ ],
758
+ "dev": true,
759
+ "license": "MIT",
760
+ "optional": true,
761
+ "os": [
762
+ "win32"
763
+ ]
764
+ },
765
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
766
+ "version": "4.52.4",
767
+ "cpu": [
768
+ "x64"
769
+ ],
770
+ "dev": true,
771
+ "license": "MIT",
772
+ "optional": true,
773
+ "os": [
774
+ "win32"
775
+ ]
776
+ },
777
+ "node_modules/@types/babel__core": {
778
+ "version": "7.20.5",
779
+ "dev": true,
780
+ "license": "MIT",
781
+ "dependencies": {
782
+ "@babel/parser": "^7.20.7",
783
+ "@babel/types": "^7.20.7",
784
+ "@types/babel__generator": "*",
785
+ "@types/babel__template": "*",
786
+ "@types/babel__traverse": "*"
787
+ }
788
+ },
789
+ "node_modules/@types/babel__generator": {
790
+ "version": "7.27.0",
791
+ "dev": true,
792
+ "license": "MIT",
793
+ "dependencies": {
794
+ "@babel/types": "^7.0.0"
795
+ }
796
+ },
797
+ "node_modules/@types/babel__template": {
798
+ "version": "7.4.4",
799
+ "dev": true,
800
+ "license": "MIT",
801
+ "dependencies": {
802
+ "@babel/parser": "^7.1.0",
803
+ "@babel/types": "^7.0.0"
804
+ }
805
+ },
806
+ "node_modules/@types/babel__traverse": {
807
+ "version": "7.28.0",
808
+ "dev": true,
809
+ "license": "MIT",
810
+ "dependencies": {
811
+ "@babel/types": "^7.28.2"
812
+ }
813
+ },
814
+ "node_modules/@types/estree": {
815
+ "version": "1.0.8",
816
+ "dev": true,
817
+ "license": "MIT"
818
+ },
819
+ "node_modules/@types/prop-types": {
820
+ "version": "15.7.15",
821
+ "dev": true,
822
+ "license": "MIT"
823
+ },
824
+ "node_modules/@types/react": {
825
+ "version": "18.3.26",
826
+ "dev": true,
827
+ "license": "MIT",
828
+ "dependencies": {
829
+ "@types/prop-types": "*",
830
+ "csstype": "^3.0.2"
831
+ }
832
+ },
833
+ "node_modules/@types/react-dom": {
834
+ "version": "18.3.7",
835
+ "dev": true,
836
+ "license": "MIT",
837
+ "peerDependencies": {
838
+ "@types/react": "^18.0.0"
839
+ }
840
+ },
841
+ "node_modules/@vitejs/plugin-react": {
842
+ "version": "4.7.0",
843
+ "dev": true,
844
+ "license": "MIT",
845
+ "dependencies": {
846
+ "@babel/core": "^7.28.0",
847
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
848
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
849
+ "@rolldown/pluginutils": "1.0.0-beta.27",
850
+ "@types/babel__core": "^7.20.5",
851
+ "react-refresh": "^0.17.0"
852
+ },
853
+ "engines": {
854
+ "node": "^14.18.0 || >=16.0.0"
855
+ },
856
+ "peerDependencies": {
857
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
858
+ }
859
+ },
860
+ "node_modules/baseline-browser-mapping": {
861
+ "version": "2.8.16",
862
+ "dev": true,
863
+ "license": "Apache-2.0",
864
+ "bin": {
865
+ "baseline-browser-mapping": "dist/cli.js"
866
+ }
867
+ },
868
+ "node_modules/browserslist": {
869
+ "version": "4.26.3",
870
+ "dev": true,
871
+ "funding": [
872
+ {
873
+ "type": "opencollective",
874
+ "url": "https://opencollective.com/browserslist"
875
+ },
876
+ {
877
+ "type": "tidelift",
878
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
879
+ },
880
+ {
881
+ "type": "github",
882
+ "url": "https://github.com/sponsors/ai"
883
+ }
884
+ ],
885
+ "license": "MIT",
886
+ "dependencies": {
887
+ "baseline-browser-mapping": "^2.8.9",
888
+ "caniuse-lite": "^1.0.30001746",
889
+ "electron-to-chromium": "^1.5.227",
890
+ "node-releases": "^2.0.21",
891
+ "update-browserslist-db": "^1.1.3"
892
+ },
893
+ "bin": {
894
+ "browserslist": "cli.js"
895
+ },
896
+ "engines": {
897
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
898
+ }
899
+ },
900
+ "node_modules/caniuse-lite": {
901
+ "version": "1.0.30001750",
902
+ "dev": true,
903
+ "funding": [
904
+ {
905
+ "type": "opencollective",
906
+ "url": "https://opencollective.com/browserslist"
907
+ },
908
+ {
909
+ "type": "tidelift",
910
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
911
+ },
912
+ {
913
+ "type": "github",
914
+ "url": "https://github.com/sponsors/ai"
915
+ }
916
+ ],
917
+ "license": "CC-BY-4.0"
918
+ },
919
+ "node_modules/convert-source-map": {
920
+ "version": "2.0.0",
921
+ "dev": true,
922
+ "license": "MIT"
923
+ },
924
+ "node_modules/csstype": {
925
+ "version": "3.1.3",
926
+ "dev": true,
927
+ "license": "MIT"
928
+ },
929
+ "node_modules/debug": {
930
+ "version": "4.4.3",
931
+ "dev": true,
932
+ "license": "MIT",
933
+ "dependencies": {
934
+ "ms": "^2.1.3"
935
+ },
936
+ "engines": {
937
+ "node": ">=6.0"
938
+ },
939
+ "peerDependenciesMeta": {
940
+ "supports-color": {
941
+ "optional": true
942
+ }
943
+ }
944
+ },
945
+ "node_modules/electron-to-chromium": {
946
+ "version": "1.5.237",
947
+ "dev": true,
948
+ "license": "ISC"
949
+ },
950
+ "node_modules/esbuild": {
951
+ "version": "0.27.2",
952
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
953
+ "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
954
+ "dev": true,
955
+ "hasInstallScript": true,
956
+ "license": "MIT",
957
+ "bin": {
958
+ "esbuild": "bin/esbuild"
959
+ },
960
+ "engines": {
961
+ "node": ">=18"
962
+ },
963
+ "optionalDependencies": {
964
+ "@esbuild/aix-ppc64": "0.27.2",
965
+ "@esbuild/android-arm": "0.27.2",
966
+ "@esbuild/android-arm64": "0.27.2",
967
+ "@esbuild/android-x64": "0.27.2",
968
+ "@esbuild/darwin-arm64": "0.27.2",
969
+ "@esbuild/darwin-x64": "0.27.2",
970
+ "@esbuild/freebsd-arm64": "0.27.2",
971
+ "@esbuild/freebsd-x64": "0.27.2",
972
+ "@esbuild/linux-arm": "0.27.2",
973
+ "@esbuild/linux-arm64": "0.27.2",
974
+ "@esbuild/linux-ia32": "0.27.2",
975
+ "@esbuild/linux-loong64": "0.27.2",
976
+ "@esbuild/linux-mips64el": "0.27.2",
977
+ "@esbuild/linux-ppc64": "0.27.2",
978
+ "@esbuild/linux-riscv64": "0.27.2",
979
+ "@esbuild/linux-s390x": "0.27.2",
980
+ "@esbuild/linux-x64": "0.27.2",
981
+ "@esbuild/netbsd-arm64": "0.27.2",
982
+ "@esbuild/netbsd-x64": "0.27.2",
983
+ "@esbuild/openbsd-arm64": "0.27.2",
984
+ "@esbuild/openbsd-x64": "0.27.2",
985
+ "@esbuild/openharmony-arm64": "0.27.2",
986
+ "@esbuild/sunos-x64": "0.27.2",
987
+ "@esbuild/win32-arm64": "0.27.2",
988
+ "@esbuild/win32-ia32": "0.27.2",
989
+ "@esbuild/win32-x64": "0.27.2"
990
+ }
991
+ },
992
+ "node_modules/escalade": {
993
+ "version": "3.2.0",
994
+ "dev": true,
995
+ "license": "MIT",
996
+ "engines": {
997
+ "node": ">=6"
998
+ }
999
+ },
1000
+ "node_modules/fdir": {
1001
+ "version": "6.5.0",
1002
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1003
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1004
+ "dev": true,
1005
+ "license": "MIT",
1006
+ "engines": {
1007
+ "node": ">=12.0.0"
1008
+ },
1009
+ "peerDependencies": {
1010
+ "picomatch": "^3 || ^4"
1011
+ },
1012
+ "peerDependenciesMeta": {
1013
+ "picomatch": {
1014
+ "optional": true
1015
+ }
1016
+ }
1017
+ },
1018
+ "node_modules/fsevents": {
1019
+ "version": "2.3.3",
1020
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1021
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1022
+ "dev": true,
1023
+ "hasInstallScript": true,
1024
+ "license": "MIT",
1025
+ "optional": true,
1026
+ "os": [
1027
+ "darwin"
1028
+ ],
1029
+ "engines": {
1030
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1031
+ }
1032
+ },
1033
+ "node_modules/gensync": {
1034
+ "version": "1.0.0-beta.2",
1035
+ "dev": true,
1036
+ "license": "MIT",
1037
+ "engines": {
1038
+ "node": ">=6.9.0"
1039
+ }
1040
+ },
1041
+ "node_modules/js-tokens": {
1042
+ "version": "4.0.0",
1043
+ "license": "MIT"
1044
+ },
1045
+ "node_modules/jsesc": {
1046
+ "version": "3.1.0",
1047
+ "dev": true,
1048
+ "license": "MIT",
1049
+ "bin": {
1050
+ "jsesc": "bin/jsesc"
1051
+ },
1052
+ "engines": {
1053
+ "node": ">=6"
1054
+ }
1055
+ },
1056
+ "node_modules/json5": {
1057
+ "version": "2.2.3",
1058
+ "dev": true,
1059
+ "license": "MIT",
1060
+ "bin": {
1061
+ "json5": "lib/cli.js"
1062
+ },
1063
+ "engines": {
1064
+ "node": ">=6"
1065
+ }
1066
+ },
1067
+ "node_modules/loose-envify": {
1068
+ "version": "1.4.0",
1069
+ "license": "MIT",
1070
+ "dependencies": {
1071
+ "js-tokens": "^3.0.0 || ^4.0.0"
1072
+ },
1073
+ "bin": {
1074
+ "loose-envify": "cli.js"
1075
+ }
1076
+ },
1077
+ "node_modules/lru-cache": {
1078
+ "version": "5.1.1",
1079
+ "dev": true,
1080
+ "license": "ISC",
1081
+ "dependencies": {
1082
+ "yallist": "^3.0.2"
1083
+ }
1084
+ },
1085
+ "node_modules/ms": {
1086
+ "version": "2.1.3",
1087
+ "dev": true,
1088
+ "license": "MIT"
1089
+ },
1090
+ "node_modules/nanoid": {
1091
+ "version": "3.3.11",
1092
+ "dev": true,
1093
+ "funding": [
1094
+ {
1095
+ "type": "github",
1096
+ "url": "https://github.com/sponsors/ai"
1097
+ }
1098
+ ],
1099
+ "license": "MIT",
1100
+ "bin": {
1101
+ "nanoid": "bin/nanoid.cjs"
1102
+ },
1103
+ "engines": {
1104
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1105
+ }
1106
+ },
1107
+ "node_modules/node-releases": {
1108
+ "version": "2.0.23",
1109
+ "dev": true,
1110
+ "license": "MIT"
1111
+ },
1112
+ "node_modules/picocolors": {
1113
+ "version": "1.1.1",
1114
+ "dev": true,
1115
+ "license": "ISC"
1116
+ },
1117
+ "node_modules/picomatch": {
1118
+ "version": "4.0.3",
1119
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
1120
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
1121
+ "dev": true,
1122
+ "license": "MIT",
1123
+ "engines": {
1124
+ "node": ">=12"
1125
+ },
1126
+ "funding": {
1127
+ "url": "https://github.com/sponsors/jonschlinkert"
1128
+ }
1129
+ },
1130
+ "node_modules/postcss": {
1131
+ "version": "8.5.6",
1132
+ "dev": true,
1133
+ "funding": [
1134
+ {
1135
+ "type": "opencollective",
1136
+ "url": "https://opencollective.com/postcss/"
1137
+ },
1138
+ {
1139
+ "type": "tidelift",
1140
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1141
+ },
1142
+ {
1143
+ "type": "github",
1144
+ "url": "https://github.com/sponsors/ai"
1145
+ }
1146
+ ],
1147
+ "license": "MIT",
1148
+ "dependencies": {
1149
+ "nanoid": "^3.3.11",
1150
+ "picocolors": "^1.1.1",
1151
+ "source-map-js": "^1.2.1"
1152
+ },
1153
+ "engines": {
1154
+ "node": "^10 || ^12 || >=14"
1155
+ }
1156
+ },
1157
+ "node_modules/react": {
1158
+ "version": "18.3.1",
1159
+ "license": "MIT",
1160
+ "dependencies": {
1161
+ "loose-envify": "^1.1.0"
1162
+ },
1163
+ "engines": {
1164
+ "node": ">=0.10.0"
1165
+ }
1166
+ },
1167
+ "node_modules/react-dom": {
1168
+ "version": "18.3.1",
1169
+ "license": "MIT",
1170
+ "dependencies": {
1171
+ "loose-envify": "^1.1.0",
1172
+ "scheduler": "^0.23.2"
1173
+ },
1174
+ "peerDependencies": {
1175
+ "react": "^18.3.1"
1176
+ }
1177
+ },
1178
+ "node_modules/react-refresh": {
1179
+ "version": "0.17.0",
1180
+ "dev": true,
1181
+ "license": "MIT",
1182
+ "engines": {
1183
+ "node": ">=0.10.0"
1184
+ }
1185
+ },
1186
+ "node_modules/rollup": {
1187
+ "version": "4.52.4",
1188
+ "dev": true,
1189
+ "license": "MIT",
1190
+ "dependencies": {
1191
+ "@types/estree": "1.0.8"
1192
+ },
1193
+ "bin": {
1194
+ "rollup": "dist/bin/rollup"
1195
+ },
1196
+ "engines": {
1197
+ "node": ">=18.0.0",
1198
+ "npm": ">=8.0.0"
1199
+ },
1200
+ "optionalDependencies": {
1201
+ "@rollup/rollup-android-arm-eabi": "4.52.4",
1202
+ "@rollup/rollup-android-arm64": "4.52.4",
1203
+ "@rollup/rollup-darwin-arm64": "4.52.4",
1204
+ "@rollup/rollup-darwin-x64": "4.52.4",
1205
+ "@rollup/rollup-freebsd-arm64": "4.52.4",
1206
+ "@rollup/rollup-freebsd-x64": "4.52.4",
1207
+ "@rollup/rollup-linux-arm-gnueabihf": "4.52.4",
1208
+ "@rollup/rollup-linux-arm-musleabihf": "4.52.4",
1209
+ "@rollup/rollup-linux-arm64-gnu": "4.52.4",
1210
+ "@rollup/rollup-linux-arm64-musl": "4.52.4",
1211
+ "@rollup/rollup-linux-loong64-gnu": "4.52.4",
1212
+ "@rollup/rollup-linux-ppc64-gnu": "4.52.4",
1213
+ "@rollup/rollup-linux-riscv64-gnu": "4.52.4",
1214
+ "@rollup/rollup-linux-riscv64-musl": "4.52.4",
1215
+ "@rollup/rollup-linux-s390x-gnu": "4.52.4",
1216
+ "@rollup/rollup-linux-x64-gnu": "4.52.4",
1217
+ "@rollup/rollup-linux-x64-musl": "4.52.4",
1218
+ "@rollup/rollup-openharmony-arm64": "4.52.4",
1219
+ "@rollup/rollup-win32-arm64-msvc": "4.52.4",
1220
+ "@rollup/rollup-win32-ia32-msvc": "4.52.4",
1221
+ "@rollup/rollup-win32-x64-gnu": "4.52.4",
1222
+ "@rollup/rollup-win32-x64-msvc": "4.52.4",
1223
+ "fsevents": "~2.3.2"
1224
+ }
1225
+ },
1226
+ "node_modules/scheduler": {
1227
+ "version": "0.23.2",
1228
+ "license": "MIT",
1229
+ "dependencies": {
1230
+ "loose-envify": "^1.1.0"
1231
+ }
1232
+ },
1233
+ "node_modules/semver": {
1234
+ "version": "6.3.1",
1235
+ "dev": true,
1236
+ "license": "ISC",
1237
+ "bin": {
1238
+ "semver": "bin/semver.js"
1239
+ }
1240
+ },
1241
+ "node_modules/source-map-js": {
1242
+ "version": "1.2.1",
1243
+ "dev": true,
1244
+ "license": "BSD-3-Clause",
1245
+ "engines": {
1246
+ "node": ">=0.10.0"
1247
+ }
1248
+ },
1249
+ "node_modules/tinyglobby": {
1250
+ "version": "0.2.15",
1251
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
1252
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
1253
+ "dev": true,
1254
+ "license": "MIT",
1255
+ "dependencies": {
1256
+ "fdir": "^6.5.0",
1257
+ "picomatch": "^4.0.3"
1258
+ },
1259
+ "engines": {
1260
+ "node": ">=12.0.0"
1261
+ },
1262
+ "funding": {
1263
+ "url": "https://github.com/sponsors/SuperchupuDev"
1264
+ }
1265
+ },
1266
+ "node_modules/typescript": {
1267
+ "version": "5.9.3",
1268
+ "dev": true,
1269
+ "license": "Apache-2.0",
1270
+ "bin": {
1271
+ "tsc": "bin/tsc",
1272
+ "tsserver": "bin/tsserver"
1273
+ },
1274
+ "engines": {
1275
+ "node": ">=14.17"
1276
+ }
1277
+ },
1278
+ "node_modules/update-browserslist-db": {
1279
+ "version": "1.1.3",
1280
+ "dev": true,
1281
+ "funding": [
1282
+ {
1283
+ "type": "opencollective",
1284
+ "url": "https://opencollective.com/browserslist"
1285
+ },
1286
+ {
1287
+ "type": "tidelift",
1288
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1289
+ },
1290
+ {
1291
+ "type": "github",
1292
+ "url": "https://github.com/sponsors/ai"
1293
+ }
1294
+ ],
1295
+ "license": "MIT",
1296
+ "dependencies": {
1297
+ "escalade": "^3.2.0",
1298
+ "picocolors": "^1.1.1"
1299
+ },
1300
+ "bin": {
1301
+ "update-browserslist-db": "cli.js"
1302
+ },
1303
+ "peerDependencies": {
1304
+ "browserslist": ">= 4.21.0"
1305
+ }
1306
+ },
1307
+ "node_modules/vite": {
1308
+ "version": "7.3.1",
1309
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
1310
+ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
1311
+ "dev": true,
1312
+ "license": "MIT",
1313
+ "dependencies": {
1314
+ "esbuild": "^0.27.0",
1315
+ "fdir": "^6.5.0",
1316
+ "picomatch": "^4.0.3",
1317
+ "postcss": "^8.5.6",
1318
+ "rollup": "^4.43.0",
1319
+ "tinyglobby": "^0.2.15"
1320
+ },
1321
+ "bin": {
1322
+ "vite": "bin/vite.js"
1323
+ },
1324
+ "engines": {
1325
+ "node": "^20.19.0 || >=22.12.0"
1326
+ },
1327
+ "funding": {
1328
+ "url": "https://github.com/vitejs/vite?sponsor=1"
1329
+ },
1330
+ "optionalDependencies": {
1331
+ "fsevents": "~2.3.3"
1332
+ },
1333
+ "peerDependencies": {
1334
+ "@types/node": "^20.19.0 || >=22.12.0",
1335
+ "jiti": ">=1.21.0",
1336
+ "less": "^4.0.0",
1337
+ "lightningcss": "^1.21.0",
1338
+ "sass": "^1.70.0",
1339
+ "sass-embedded": "^1.70.0",
1340
+ "stylus": ">=0.54.8",
1341
+ "sugarss": "^5.0.0",
1342
+ "terser": "^5.16.0",
1343
+ "tsx": "^4.8.1",
1344
+ "yaml": "^2.4.2"
1345
+ },
1346
+ "peerDependenciesMeta": {
1347
+ "@types/node": {
1348
+ "optional": true
1349
+ },
1350
+ "jiti": {
1351
+ "optional": true
1352
+ },
1353
+ "less": {
1354
+ "optional": true
1355
+ },
1356
+ "lightningcss": {
1357
+ "optional": true
1358
+ },
1359
+ "sass": {
1360
+ "optional": true
1361
+ },
1362
+ "sass-embedded": {
1363
+ "optional": true
1364
+ },
1365
+ "stylus": {
1366
+ "optional": true
1367
+ },
1368
+ "sugarss": {
1369
+ "optional": true
1370
+ },
1371
+ "terser": {
1372
+ "optional": true
1373
+ },
1374
+ "tsx": {
1375
+ "optional": true
1376
+ },
1377
+ "yaml": {
1378
+ "optional": true
1379
+ }
1380
+ }
1381
+ },
1382
+ "node_modules/yallist": {
1383
+ "version": "3.1.1",
1384
+ "dev": true,
1385
+ "license": "ISC"
1386
+ }
1387
+ }
1388
+ }
frontend/package.json CHANGED
@@ -17,6 +17,6 @@
17
  "@types/react-dom": "^18.3.3",
18
  "@vitejs/plugin-react": "^4.3.1",
19
  "typescript": "^5.4.5",
20
- "vite": "^5.4.8"
21
  }
22
  }
 
17
  "@types/react-dom": "^18.3.3",
18
  "@vitejs/plugin-react": "^4.3.1",
19
  "typescript": "^5.4.5",
20
+ "vite": "^7.3.1"
21
  }
22
  }
frontend/src/{styles.css → index.css} RENAMED
@@ -2,14 +2,20 @@
2
  box-sizing: border-box;
3
  }
4
 
5
- body {
 
 
 
 
6
  margin: 0;
 
 
 
7
  background: #000000;
8
  }
9
 
10
- #root,
11
  .black-screen {
12
- width: 100vw;
13
- height: 100vh;
14
  background: #000000;
15
  }
 
2
  box-sizing: border-box;
3
  }
4
 
5
+ html,
6
+ body,
7
+ #root {
8
+ width: 100%;
9
+ height: 100%;
10
  margin: 0;
11
+ }
12
+
13
+ body {
14
  background: #000000;
15
  }
16
 
 
17
  .black-screen {
18
+ width: 100%;
19
+ height: 100%;
20
  background: #000000;
21
  }
frontend/src/main.tsx CHANGED
@@ -1,7 +1,7 @@
1
  import React from "react";
2
  import ReactDOM from "react-dom/client";
3
  import App from "./App";
4
- import "./styles.css";
5
 
6
  ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
7
  <React.StrictMode>
 
1
  import React from "react";
2
  import ReactDOM from "react-dom/client";
3
  import App from "./App";
4
+ import "./index.css";
5
 
6
  ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
7
  <React.StrictMode>
frontend/src/vite-env.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ /// <reference types="vite/client" />
package-lock.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "name": "RepEx",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {}
6
+ }
server/app/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- from .main import create_app
2
 
3
- __all__ = ["create_app"]
 
1
+ from .main import app, create_app
2
 
3
+ __all__ = ["app", "create_app"]
server/app/api/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .router import api_router
2
+
3
+ __all__ = ["api_router"]
server/app/api/router.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter
2
+
3
+ from .routes.health import router as health_router
4
+
5
+ api_router = APIRouter()
6
+ api_router.include_router(health_router, tags=["system"])
7
+
8
+ __all__ = ["api_router"]
server/app/api/routes/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .health import router as health_router
2
+
3
+ __all__ = ["health_router"]
server/app/api/routes/health.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter
2
+
3
+ router = APIRouter()
4
+
5
+
6
+ @router.get("/health", summary="Health check")
7
+ async def healthcheck() -> dict[str, str]:
8
+ return {"status": "ok"}
server/app/core/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .config import Settings, get_settings
2
+
3
+ __all__ = ["Settings", "get_settings"]
server/app/core/config.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from dataclasses import dataclass
5
+ from functools import lru_cache
6
+ from typing import List
7
+
8
+
9
+ def _split_csv(value: str | None, *, fallback: List[str]) -> List[str]:
10
+ if not value:
11
+ return fallback
12
+ return [item.strip() for item in value.split(",") if item.strip()]
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class Settings:
17
+ app_name: str
18
+ api_prefix: str
19
+ cors_origins: List[str]
20
+
21
+
22
+ @lru_cache
23
+ def get_settings() -> Settings:
24
+ return Settings(
25
+ app_name=os.getenv("APP_NAME", "Starter API"),
26
+ api_prefix=os.getenv("API_PREFIX", "/api"),
27
+ cors_origins=_split_csv(
28
+ os.getenv("CORS_ORIGINS"), fallback=["http://localhost:5173"]
29
+ ),
30
+ )
server/app/main.py CHANGED
@@ -1,22 +1,22 @@
1
  from fastapi import FastAPI
2
  from fastapi.middleware.cors import CORSMiddleware
3
 
 
 
 
4
 
5
  def create_app() -> FastAPI:
6
- app = FastAPI(title="Starter API", version="0.1.0")
7
 
 
8
  app.add_middleware(
9
  CORSMiddleware,
10
- allow_origins=["http://localhost:5173"],
11
  allow_credentials=True,
12
  allow_methods=["*"],
13
  allow_headers=["*"],
14
  )
15
-
16
- @app.get("/health", summary="Health check")
17
- async def healthcheck() -> dict[str, str]:
18
- return {"status": "ok"}
19
-
20
  return app
21
 
22
 
 
1
  from fastapi import FastAPI
2
  from fastapi.middleware.cors import CORSMiddleware
3
 
4
+ from .api.router import api_router
5
+ from .core.config import get_settings
6
+
7
 
8
  def create_app() -> FastAPI:
9
+ settings = get_settings()
10
 
11
+ app = FastAPI(title=settings.app_name, version="0.1.0")
12
  app.add_middleware(
13
  CORSMiddleware,
14
+ allow_origins=settings.cors_origins,
15
  allow_credentials=True,
16
  allow_methods=["*"],
17
  allow_headers=["*"],
18
  )
19
+ app.include_router(api_router, prefix=settings.api_prefix)
 
 
 
 
20
  return app
21
 
22