stackkit-cli 0.4.3 → 0.4.5

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.
Files changed (102) hide show
  1. package/README.md +26 -2
  2. package/bin/stackkit.js +10 -1
  3. package/dist/commands/add.js +128 -10
  4. package/dist/commands/doctor.d.ts +11 -0
  5. package/dist/commands/doctor.js +483 -0
  6. package/dist/commands/list.d.ts +1 -1
  7. package/dist/commands/list.js +59 -38
  8. package/dist/index.js +11 -13
  9. package/dist/types/index.d.ts +29 -2
  10. package/dist/utils/config-utils.d.ts +2 -0
  11. package/dist/utils/config-utils.js +88 -0
  12. package/dist/utils/detect.js +12 -2
  13. package/dist/utils/env-editor.d.ts +0 -1
  14. package/dist/utils/env-editor.js +50 -25
  15. package/dist/utils/files.d.ts +8 -0
  16. package/dist/utils/files.js +51 -0
  17. package/dist/utils/js-conversion.d.ts +1 -0
  18. package/dist/utils/js-conversion.js +244 -0
  19. package/dist/utils/module-utils.d.ts +2 -0
  20. package/dist/utils/module-utils.js +461 -0
  21. package/dist/utils/package-manager.js +15 -31
  22. package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
  23. package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
  24. package/modules/auth/authjs/files/lib/auth.ts +41 -0
  25. package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
  26. package/modules/auth/authjs/module.json +95 -0
  27. package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
  28. package/modules/auth/better-auth/files/lib/auth.ts +75 -0
  29. package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
  30. package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
  31. package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +63 -0
  32. package/modules/auth/better-auth/module.json +191 -0
  33. package/modules/database/mongoose/files/lib/db.ts +68 -0
  34. package/modules/database/mongoose/files/models/User.ts +34 -0
  35. package/modules/database/mongoose/module.json +55 -0
  36. package/modules/database/prisma/files/lib/prisma.ts +4 -0
  37. package/modules/database/prisma/files/prisma/schema.prisma +8 -0
  38. package/modules/database/prisma/files/prisma.config.ts +12 -0
  39. package/modules/database/prisma/module.json +122 -0
  40. package/package.json +1 -1
  41. package/templates/express/.env.example +1 -10
  42. package/templates/express/package.json +15 -21
  43. package/templates/express/src/app.ts +9 -29
  44. package/templates/express/src/config/env.ts +3 -14
  45. package/templates/express/src/features/health/health.controller.ts +18 -0
  46. package/templates/express/src/features/health/health.route.ts +9 -0
  47. package/templates/express/src/features/health/health.service.ts +6 -0
  48. package/templates/express/src/middlewares/error.middleware.ts +2 -2
  49. package/templates/express/src/server.ts +1 -1
  50. package/templates/express/template.json +1 -5
  51. package/templates/express/tsconfig.json +0 -1
  52. package/templates/nextjs/lib/env.ts +8 -0
  53. package/templates/nextjs/package.json +7 -7
  54. package/templates/react-vite/.env.example +1 -2
  55. package/templates/react-vite/.prettierignore +4 -0
  56. package/templates/react-vite/.prettierrc +9 -0
  57. package/templates/react-vite/README.md +22 -0
  58. package/templates/react-vite/package.json +16 -16
  59. package/templates/react-vite/src/router.tsx +0 -12
  60. package/templates/react-vite/vite.config.ts +0 -6
  61. package/dist/commands/init.d.ts +0 -10
  62. package/dist/commands/init.js +0 -157
  63. package/dist/utils/code-inject.d.ts +0 -14
  64. package/dist/utils/code-inject.js +0 -70
  65. package/dist/utils/json-editor.d.ts +0 -8
  66. package/dist/utils/json-editor.js +0 -45
  67. package/modules/auth/better-auth-express/adapters/mongoose-mongodb.ts +0 -13
  68. package/modules/auth/better-auth-express/adapters/prisma-mongodb.ts +0 -15
  69. package/modules/auth/better-auth-express/adapters/prisma-postgresql.ts +0 -15
  70. package/modules/auth/better-auth-express/files/lib/auth.ts +0 -16
  71. package/modules/auth/better-auth-express/files/routes/auth.ts +0 -12
  72. package/modules/auth/better-auth-express/files/schemas/prisma-mongodb-schema.prisma +0 -72
  73. package/modules/auth/better-auth-express/files/schemas/prisma-postgresql-schema.prisma +0 -72
  74. package/modules/auth/better-auth-express/module.json +0 -61
  75. package/modules/auth/better-auth-nextjs/adapters/mongoose-mongodb.ts +0 -24
  76. package/modules/auth/better-auth-nextjs/adapters/prisma-mongodb.ts +0 -26
  77. package/modules/auth/better-auth-nextjs/adapters/prisma-postgresql.ts +0 -26
  78. package/modules/auth/better-auth-nextjs/files/lib/auth.ts +0 -26
  79. package/modules/auth/better-auth-nextjs/files/schemas/prisma-mongodb-schema.prisma +0 -72
  80. package/modules/auth/better-auth-nextjs/files/schemas/prisma-postgresql-schema.prisma +0 -72
  81. package/modules/auth/better-auth-nextjs/module.json +0 -62
  82. package/modules/auth/better-auth-react/files/lib/auth-client.ts +0 -9
  83. package/modules/auth/better-auth-react/module.json +0 -28
  84. package/modules/auth/clerk-express/files/lib/auth.ts +0 -7
  85. package/modules/auth/clerk-express/module.json +0 -34
  86. package/modules/auth/clerk-nextjs/files/lib/auth-provider.tsx +0 -5
  87. package/modules/auth/clerk-nextjs/files/middleware.ts +0 -9
  88. package/modules/auth/clerk-nextjs/module.json +0 -64
  89. package/modules/auth/clerk-react/files/lib/auth-provider.tsx +0 -15
  90. package/modules/auth/clerk-react/module.json +0 -28
  91. package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -40
  92. package/modules/database/mongoose-mongodb/module.json +0 -55
  93. package/modules/database/prisma-mongodb/files/lib/db.ts +0 -9
  94. package/modules/database/prisma-mongodb/files/prisma/schema.prisma +0 -17
  95. package/modules/database/prisma-mongodb/module.json +0 -60
  96. package/modules/database/prisma-postgresql/files/lib/db.ts +0 -9
  97. package/modules/database/prisma-postgresql/files/prisma/schema.prisma +0 -17
  98. package/modules/database/prisma-postgresql/module.json +0 -60
  99. package/templates/react-vite/src/api/services/user.service.ts +0 -18
  100. package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
  101. package/templates/react-vite/src/types/user.d.ts +0 -6
  102. /package/modules/auth/{better-auth-nextjs → better-auth}/files/api/auth/[...all]/route.ts +0 -0
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "mongoose",
3
+ "displayName": "Mongoose (MongoDB)",
4
+ "description": "Mongoose ODM for MongoDB database",
5
+ "category": "database",
6
+ "provider": "mongoose",
7
+ "database": "mongodb",
8
+ "supportedFrameworks": ["nextjs", "express"],
9
+ "dependencies": {
10
+ "mongoose": "^8.8.4",
11
+ "mongodb": "^6.10.0"
12
+ },
13
+ "devDependencies": {
14
+ "@types/mongoose": "^5.11.97"
15
+ },
16
+ "envVars": {
17
+ "common": [
18
+ {
19
+ "key": "DATABASE_URL",
20
+ "value": "mongodb+srv://username:password@cluster.mongodb.net/mydb",
21
+ "required": true
22
+ }
23
+ ]
24
+ },
25
+ "frameworkPatches": {
26
+ "express": {
27
+ "tsconfig.json": {
28
+ "merge": {
29
+ "compilerOptions": {
30
+ "baseUrl": ".",
31
+ "paths": {
32
+ "@/*": ["./*"]
33
+ }
34
+ },
35
+ "include": ["src/**/*", "lib/**/*"],
36
+ "exclude": ["node_modules", "dist"]
37
+ }
38
+ }
39
+ }
40
+ },
41
+ "patches": [
42
+ {
43
+ "type": "create-file",
44
+ "description": "{{dbDescription}}",
45
+ "source": "lib/{{dbFile}}",
46
+ "destination": "{{lib}}/{{dbFile}}"
47
+ },
48
+ {
49
+ "type": "create-file",
50
+ "description": "Create sample User model",
51
+ "source": "models/User.ts",
52
+ "destination": "{{models}}/User.ts"
53
+ }
54
+ ]
55
+ }
@@ -0,0 +1,4 @@
1
+ import "dotenv/config";
2
+ import { PrismaClient } from "./generated/prisma/client";
3
+ {{prismaClientInit}}
4
+ export { prisma };
@@ -0,0 +1,8 @@
1
+ generator client {
2
+ provider = "prisma-client"
3
+ output = "../lib/generated/prisma"
4
+ }
5
+
6
+ datasource db {
7
+ provider = "{{provider}}"
8
+ }
@@ -0,0 +1,12 @@
1
+ import "dotenv/config";
2
+ import { defineConfig, env } from "prisma/config";
3
+
4
+ export default defineConfig({
5
+ schema: "prisma/schema.prisma",
6
+ migrations: {
7
+ path: "prisma/migrations",
8
+ },
9
+ datasource: {
10
+ url: env('DATABASE_URL'),
11
+ },
12
+ });
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "prisma",
3
+ "displayName": "Prisma",
4
+ "description": "Prisma ORM",
5
+ "category": "database",
6
+ "provider": "prisma",
7
+ "supportedFrameworks": ["nextjs", "express"],
8
+ "dependencies": {
9
+ "common": {
10
+ "@prisma/client": "^7.2.0",
11
+ "dotenv": "^17.2.3"
12
+ },
13
+ "providers": {
14
+ "postgresql": {
15
+ "@prisma/adapter-pg": "^7.2.0",
16
+ "pg": "^8.16.3"
17
+ },
18
+ "mongodb": {
19
+ "@prisma/client": "6.19"
20
+ },
21
+ "mysql": {
22
+ "@prisma/adapter-mariadb": "^7.2.0"
23
+ },
24
+ "sqlite": {
25
+ "@prisma/adapter-better-sqlite3": "^7.2.0"
26
+ }
27
+ }
28
+ },
29
+ "devDependencies": {
30
+ "common": {
31
+ "prisma": "^7.2.0",
32
+ "tsx": "^4.21.0"
33
+ },
34
+ "providers": {
35
+ "postgresql": {
36
+ "@types/pg": "^8.16.0"
37
+ },
38
+ "mongodb": {
39
+ "prisma": "6.19"
40
+ },
41
+ "mysql": {},
42
+ "sqlite": {
43
+ "@types/better-sqlite3": "^7.6.13"
44
+ }
45
+ }
46
+ },
47
+ "envVars": {
48
+ "common": [
49
+ {
50
+ "key": "DATABASE_URL",
51
+ "value": "{{connectionString}}",
52
+ "required": true
53
+ }
54
+ ],
55
+ "providers": {
56
+ "mysql": [
57
+ {
58
+ "key": "DATABASE_HOST",
59
+ "value": "localhost",
60
+ "required": true
61
+ },
62
+ {
63
+ "key": "DATABASE_USER",
64
+ "value": "",
65
+ "required": true
66
+ },
67
+ {
68
+ "key": "DATABASE_PASSWORD",
69
+ "value": "",
70
+ "required": true
71
+ },
72
+ {
73
+ "key": "DATABASE_NAME",
74
+ "value": "mydb",
75
+ "required": true
76
+ },
77
+ {
78
+ "key": "DATABASE_PORT",
79
+ "value": "3306",
80
+ "required": false
81
+ }
82
+ ]
83
+ }
84
+ },
85
+ "frameworkPatches": {
86
+ "express": {
87
+ "tsconfig.json": {
88
+ "merge": {
89
+ "compilerOptions": {
90
+ "baseUrl": ".",
91
+ "paths": {
92
+ "@/*": ["./*"]
93
+ }
94
+ },
95
+ "include": ["src/**/*", "lib/**/*"],
96
+ "exclude": ["node_modules", "dist", "lib/generated/prisma"]
97
+ }
98
+ }
99
+ }
100
+ },
101
+ "patches": [
102
+ {
103
+ "type": "create-file",
104
+ "description": "Create Prisma schema",
105
+ "source": "prisma/schema.prisma",
106
+ "destination": "prisma/schema.prisma"
107
+ },
108
+ {
109
+ "type": "create-file",
110
+ "description": "Create Prisma config",
111
+ "source": "prisma.config.ts",
112
+ "destination": "prisma.config.ts"
113
+ },
114
+ {
115
+ "type": "create-file",
116
+ "description": "{{dbDescription}}",
117
+ "source": "lib/{{dbFile}}",
118
+ "destination": "{{lib}}/{{dbFile}}"
119
+ }
120
+ ],
121
+ "postInstall": ["npx prisma generate"]
122
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stackkit-cli",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "CLI for StackKit - Production-ready project generator and module system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1,11 +1,2 @@
1
1
  PORT=3000
2
- NODE_ENV=development
3
- APP_URL=http://localhost:3000
4
- SITE_URL=http://localhost:5173
5
-
6
- # Proxy (set to true if running behind a proxy/load-balancer)
7
- TRUST_PROXY=false
8
-
9
- # Rate limit
10
- RATE_LIMIT_MAX=100
11
- RATE_LIMIT_WINDOW_MS=900000
2
+ NODE_ENV=development
@@ -1,12 +1,10 @@
1
1
  {
2
- "name": "my-app",
2
+ "name": "my-express-app",
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "tsx watch src/server.ts",
8
- "clean": "rimraf dist",
9
- "prebuild": "npm run clean",
10
8
  "build": "tsc",
11
9
  "lint": "eslint src --ext .ts",
12
10
  "lint:fix": "eslint src --ext .ts --fix",
@@ -14,26 +12,22 @@
14
12
  "start:prod": "cross-env NODE_ENV=production node dist/server.js"
15
13
  },
16
14
  "dependencies": {
17
- "compression": "^1.7.4",
18
15
  "cors": "^2.8.5",
19
- "dotenv": "^16.4.7",
20
- "express": "^4.21.2",
21
- "express-rate-limit": "^6.7.0",
22
- "helmet": "^7.0.0",
23
- "morgan": "^1.10.0"
16
+ "dotenv": "^17.2.3",
17
+ "express": "^5.2.1",
18
+ "helmet": "^8.1.0",
19
+ "morgan": "^1.10.1"
24
20
  },
25
21
  "devDependencies": {
26
- "@types/compression": "^1.8.1",
27
- "@types/cors": "^2.8.17",
28
- "@types/express": "^4.17.21",
29
- "@types/morgan": "^1.9.4",
30
- "@types/node": "^22.10.5",
31
- "@typescript-eslint/eslint-plugin": "^8.52.0",
32
- "@typescript-eslint/parser": "^8.52.0",
33
- "cross-env": "^7.0.3",
22
+ "@types/cors": "^2.8.19",
23
+ "@types/express": "^5.0.6",
24
+ "@types/morgan": "^1.9.10",
25
+ "@types/node": "^25.0.8",
26
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
27
+ "@typescript-eslint/parser": "^8.53.0",
28
+ "cross-env": "^10.1.0",
34
29
  "eslint": "^9.39.2",
35
- "rimraf": "^5.0.0",
36
- "tsx": "^4.19.2",
37
- "typescript": "^5.7.2"
30
+ "tsx": "^4.21.0",
31
+ "typescript": "^5.9.3"
38
32
  }
39
- }
33
+ }
@@ -1,54 +1,31 @@
1
- import compression from "compression";
2
1
  import cors from "cors";
3
2
  import express, { Application, NextFunction, Request, Response } from "express";
4
- import rateLimit from "express-rate-limit";
5
3
  import helmet from "helmet";
6
4
  import morgan from "morgan";
7
5
  import { env } from "./config/env";
6
+ import { authRoutes } from "./features/health/health.route";
8
7
  import { errorHandler } from "./middlewares/error.middleware";
9
8
 
10
9
  // app initialization
11
10
  const app: Application = express();
12
11
  app.use(express.json());
13
12
 
14
- // trust proxy when behind reverse proxy (like Heroku, Vercel, Load Balancers)
15
- if (env.app.trust_proxy) {
16
- app.set("trust proxy", 1);
17
- }
18
-
19
13
  // security headers
20
14
  app.use(helmet());
21
15
 
22
- // response compression
23
- app.use(compression());
24
-
25
- // rate limiting
26
- const limiter = rateLimit({
27
- windowMs: env.app.rateLimit.windowMs,
28
- max: env.app.rateLimit.max,
29
- standardHeaders: true,
30
- legacyHeaders: false,
31
- });
32
- app.use(limiter);
33
-
34
16
  // logging
35
- if (env.node.isProduction) {
17
+ if (env.isProduction) {
36
18
  app.use(morgan("combined"));
37
19
  } else {
38
20
  app.use(morgan("dev"));
39
21
  }
40
22
 
41
23
  // cors configuration
42
- app.use(
43
- cors({
44
- origin: [env.app.site_url],
45
- credentials: true,
46
- }),
47
- );
24
+ app.use(cors());
48
25
 
49
26
  // Home page route
50
- app.get("/", (req: Request, res: Response) => {
51
- res.json({
27
+ app.get("/", (_req: Request, res: Response) => {
28
+ res.status(200).json({
52
29
  title: "Welcome to your Express app",
53
30
  description:
54
31
  "Built with StackKit - A production-ready Express template with TypeScript, security, and best practices.",
@@ -57,8 +34,11 @@ app.get("/", (req: Request, res: Response) => {
57
34
  });
58
35
  });
59
36
 
37
+ // routes
38
+ app.use("/api/health", authRoutes);
39
+
60
40
  // unhandled routes
61
- app.use((req: Request, res: Response, next: NextFunction) => {
41
+ app.use((req: Request, _res: Response, next: NextFunction) => {
62
42
  const error: any = new Error(`Can't find ${req.originalUrl} on this server!`);
63
43
  error.status = 404;
64
44
 
@@ -4,20 +4,9 @@ import path from "path";
4
4
  dotenv.config({ path: path.join(process.cwd(), ".env") });
5
5
 
6
6
  const env = {
7
- app: {
8
- port: Number(process.env.PORT) || 3000,
9
- url: process.env.APP_URL || "http://localhost:3000",
10
- site_url: process.env.SITE_URL || "http://localhost:5173",
11
- trust_proxy: (process.env.TRUST_PROXY || "false") === "true",
12
- rateLimit: {
13
- max: Number(process.env.RATE_LIMIT_MAX) || 100,
14
- windowMs: Number(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000,
15
- },
16
- },
17
- node: {
18
- env: process.env.NODE_ENV || "development",
19
- isProduction: (process.env.NODE_ENV || "development") === "production",
20
- },
7
+ port: Number(process.env.PORT) || 3000,
8
+ node_env: process.env.NODE_ENV || "development",
9
+ isProduction: (process.env.NODE_ENV || "development") === "production",
21
10
  };
22
11
 
23
12
  export { env };
@@ -0,0 +1,18 @@
1
+ import { NextFunction, Request, Response } from "express";
2
+
3
+ const health = async (_req: Request, res: Response, next: NextFunction) => {
4
+ try {
5
+ res.status(200).json({
6
+ success: true,
7
+ message: "API is healthy!",
8
+ timestamp: new Date().toISOString(),
9
+ version: "1.0.0",
10
+ });
11
+ } catch (error) {
12
+ next(error);
13
+ }
14
+ };
15
+
16
+ export const healthController = {
17
+ health,
18
+ };
@@ -0,0 +1,9 @@
1
+ import { Router } from "express";
2
+ import { healthController } from "./health.controller";
3
+
4
+ const router = Router();
5
+
6
+ // demo route
7
+ router.get("/", healthController.health);
8
+
9
+ export const authRoutes = router;
@@ -0,0 +1,6 @@
1
+ // Demo service - placeholder for future use
2
+ // Add your service logic here when needed
3
+
4
+ export const healthServices = {
5
+ // placeholder
6
+ };
@@ -1,7 +1,7 @@
1
1
  import { NextFunction, Request, Response } from "express";
2
2
  import { env } from "../config/env";
3
3
 
4
- export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
4
+ export const errorHandler = (err: any, _req: Request, res: Response, _: NextFunction) => {
5
5
  const statusCode = err.status || 500;
6
6
  const errorMessage = err?.message || "Internal server error!";
7
7
 
@@ -10,7 +10,7 @@ export const errorHandler = (err: any, req: Request, res: Response, next: NextFu
10
10
  message: errorMessage,
11
11
  };
12
12
 
13
- if (!env.node.isProduction) {
13
+ if (!env.isProduction) {
14
14
  payload.errors = err?.stack || err;
15
15
  }
16
16
 
@@ -1,7 +1,7 @@
1
1
  import app from "./app";
2
2
  import { env } from "./config/env";
3
3
 
4
- const port = env.app.port;
4
+ const port = env.port;
5
5
 
6
6
  app.listen(port, () => {
7
7
  console.log(`Server is running on http://localhost:${port}`);
@@ -3,11 +3,9 @@
3
3
  "displayName": "Express.js",
4
4
  "framework": "express",
5
5
  "description": "Express.js REST API with TypeScript",
6
- "files": ["src/", ".env.example", ".gitignore", "package.json", "tsconfig.json"],
6
+ "files": ["src/", ".gitignore", "package.json", "tsconfig.json", ".env.example"],
7
7
  "scripts": {
8
8
  "dev": "tsx watch src/server.ts",
9
- "clean": "rimraf dist",
10
- "prebuild": "npm run clean",
11
9
  "build": "tsc",
12
10
  "lint": "eslint src --ext .ts",
13
11
  "lint:fix": "eslint src --ext .ts --fix",
@@ -16,8 +14,6 @@
16
14
  },
17
15
  "jsScripts": {
18
16
  "dev": "tsx --watch src/server.js",
19
- "clean": "rimraf dist",
20
- "prebuild": "npm run clean",
21
17
  "build": "echo 'No build step for JavaScript'",
22
18
  "lint": "eslint src --ext .js",
23
19
  "lint:fix": "eslint src --ext .js --fix",
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "rootDir": "./src",
4
3
  "outDir": "./dist",
5
4
  "module": "ESNext",
6
5
  "moduleResolution": "node",
@@ -0,0 +1,8 @@
1
+ export const env = {
2
+ app: {
3
+ url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
4
+ },
5
+
6
+ isDev: process.env.NODE_ENV === "development",
7
+ isProd: process.env.NODE_ENV === "production",
8
+ } as const;
@@ -15,13 +15,13 @@
15
15
  "react-dom": "19.2.3"
16
16
  },
17
17
  "devDependencies": {
18
- "@tailwindcss/postcss": "^4",
19
- "@types/node": "^20",
20
- "@types/react": "^19",
21
- "@types/react-dom": "^19",
22
- "eslint": "^9",
18
+ "@tailwindcss/postcss": "^4.1.18",
19
+ "@types/node": "^25.0.8",
20
+ "@types/react": "^19.2.8",
21
+ "@types/react-dom": "^19.2.3",
22
+ "eslint": "^9.39.2",
23
23
  "eslint-config-next": "16.1.1",
24
- "tailwindcss": "^4",
25
- "typescript": "^5"
24
+ "tailwindcss": "^4.1.18",
25
+ "typescript": "^5.9.3"
26
26
  }
27
27
  }
@@ -1,2 +1 @@
1
- # API Configuration
2
- VITE_API_URL=http://localhost:3000
1
+ VITE_API_URL=http://localhost:3000
@@ -0,0 +1,4 @@
1
+ dist
2
+ node_modules
3
+ coverage
4
+ *.log
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "all",
4
+ "singleQuote": false,
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "arrowParens": "always"
9
+ }
@@ -14,6 +14,7 @@ A production-ready React starter template with TypeScript, Vite, and essential l
14
14
  - **SEO Ready** with React Helmet Async
15
15
  - **Error Boundaries** for graceful error handling
16
16
  - **ESLint** for code quality
17
+ - **Prettier** for code formatting
17
18
  - **Custom Hooks** included
18
19
 
19
20
  ## Quick Start
@@ -30,6 +31,18 @@ pnpm build
30
31
 
31
32
  # Preview production build
32
33
  pnpm preview
34
+
35
+ # Run linter
36
+ pnpm lint
37
+
38
+ # Fix linting issues
39
+ pnpm lint:fix
40
+
41
+ # Format code
42
+ pnpm format
43
+
44
+ # Check formatting
45
+ pnpm format:check
33
46
  ```
34
47
 
35
48
  ## Project Structure
@@ -44,6 +57,7 @@ src/
44
57
  ├── pages/ # Route pages
45
58
  ├── types/ # TypeScript types
46
59
  ├── utils/ # Helper functions
60
+ ├── test/ # Test setup
47
61
  ├── App.tsx # Main app component
48
62
  ├── main.tsx # Entry point
49
63
  └── index.css # Global styles
@@ -51,6 +65,14 @@ src/
51
65
 
52
66
  ## Environment Variables
53
67
 
68
+ Copy `.env.example` to `.env` and update the values:
69
+
70
+ ```bash
71
+ cp .env.example .env
72
+ ```
73
+
74
+ ## Environment Variables
75
+
54
76
  Create a `.env` file:
55
77
 
56
78
  ```env
@@ -12,33 +12,33 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@tailwindcss/vite": "^4.1.18",
15
- "@tanstack/react-query": "^5.62.0",
16
- "@tanstack/react-query-devtools": "^5.62.0",
17
- "axios": "^1.7.7",
15
+ "@tanstack/react-query": "^5.90.16",
16
+ "@tanstack/react-query-devtools": "^5.91.2",
17
+ "axios": "^1.13.2",
18
18
  "class-variance-authority": "^0.7.1",
19
19
  "clsx": "^2.1.1",
20
- "react": "^19.2.0",
21
- "react-dom": "^19.2.0",
20
+ "react": "^19.2.3",
21
+ "react-dom": "^19.2.3",
22
22
  "react-helmet-async": "^2.0.5",
23
- "react-hot-toast": "^2.4.1",
23
+ "react-hot-toast": "^2.6.0",
24
24
  "react-router": "^7.12.0",
25
25
  "tailwind-merge": "^3.4.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@eslint/js": "^9.39.1",
29
- "@types/node": "^24.10.1",
30
- "@types/react": "^19.2.5",
28
+ "@eslint/js": "^9.39.2",
29
+ "@types/node": "^25.0.8",
30
+ "@types/react": "^19.2.8",
31
31
  "@types/react-dom": "^19.2.3",
32
- "@vitejs/plugin-react": "^5.1.1",
32
+ "@vitejs/plugin-react": "^5.1.2",
33
33
  "autoprefixer": "^10.4.23",
34
- "eslint": "^9.39.1",
34
+ "eslint": "^9.39.2",
35
35
  "eslint-plugin-react-hooks": "^7.0.1",
36
- "eslint-plugin-react-refresh": "^0.4.24",
37
- "globals": "^16.5.0",
36
+ "eslint-plugin-react-refresh": "^0.4.26",
37
+ "globals": "^17.0.0",
38
38
  "postcss": "^8.5.6",
39
39
  "tailwindcss": "^4.1.18",
40
40
  "typescript": "~5.9.3",
41
- "typescript-eslint": "^8.46.4",
42
- "vite": "^7.2.4"
41
+ "typescript-eslint": "^8.53.0",
42
+ "vite": "^7.3.1"
43
43
  }
44
- }
44
+ }
@@ -1,11 +1,9 @@
1
1
  import { createBrowserRouter } from "react-router";
2
- import { userService } from "./api/services/user.service";
3
2
  import { ErrorBoundary } from "./components/ErrorBoundary";
4
3
  import Layout from "./components/Layout";
5
4
  import About from "./pages/About";
6
5
  import Home from "./pages/Home";
7
6
  import NotFound from "./pages/NotFound";
8
- import UserProfile from "./pages/UserProfile";
9
7
 
10
8
  export const router = createBrowserRouter([
11
9
  {
@@ -15,16 +13,6 @@ export const router = createBrowserRouter([
15
13
  children: [
16
14
  { index: true, Component: Home },
17
15
  { path: "about", Component: About },
18
- {
19
- path: "users/:userId",
20
- loader: async ({ params }) => {
21
- const id = params.userId;
22
- if (!id) throw new Response("Missing user id", { status: 400 });
23
- const user = await userService.getUser(id);
24
- return user;
25
- },
26
- Component: UserProfile,
27
- },
28
16
  { path: "*", Component: NotFound },
29
17
  ],
30
18
  },