@aditokmo/create-react-project 0.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.
Files changed (82) hide show
  1. package/README.md +150 -0
  2. package/dist/index.js +129 -0
  3. package/dist/installers.js +30 -0
  4. package/dist/mapper.js +28 -0
  5. package/dist/packages.js +62 -0
  6. package/dist/questions.js +123 -0
  7. package/dist/types.js +1 -0
  8. package/dist/utils.js +101 -0
  9. package/package.json +65 -0
  10. package/templates/base/README.md +73 -0
  11. package/templates/base/eslint.config.js +23 -0
  12. package/templates/base/index.html +15 -0
  13. package/templates/base/package.json +14 -0
  14. package/templates/base/public/vite.svg +1 -0
  15. package/templates/base/src/App.tsx +9 -0
  16. package/templates/base/src/api/api.ts +29 -0
  17. package/templates/base/src/api/http.ts +27 -0
  18. package/templates/base/src/api/index.ts +2 -0
  19. package/templates/base/src/assets/react.svg +1 -0
  20. package/templates/base/src/layout/AuthLayout.tsx +0 -0
  21. package/templates/base/src/layout/MainLayout.tsx +0 -0
  22. package/templates/base/src/layout/index.ts +2 -0
  23. package/templates/base/src/main.tsx +9 -0
  24. package/templates/base/src/modules/auth/components/AuthForm.tsx +5 -0
  25. package/templates/base/src/modules/auth/hooks/useAuth.ts +55 -0
  26. package/templates/base/src/modules/auth/pages/ForgotPassword.tsx +5 -0
  27. package/templates/base/src/modules/auth/pages/Login.tsx +5 -0
  28. package/templates/base/src/modules/auth/pages/Register.tsx +5 -0
  29. package/templates/base/src/modules/auth/pages/index.ts +3 -0
  30. package/templates/base/src/modules/auth/services/auth.service.ts +17 -0
  31. package/templates/base/src/modules/auth/services/endpoint.ts +10 -0
  32. package/templates/base/src/modules/auth/services/index.ts +3 -0
  33. package/templates/base/src/modules/auth/services/oauth.service.ts +1 -0
  34. package/templates/base/src/modules/auth/services/password.service.ts +1 -0
  35. package/templates/base/src/modules/auth/types/auth.types.ts +3 -0
  36. package/templates/base/src/modules/auth/types/index.ts +3 -0
  37. package/templates/base/src/modules/auth/types/oauth.types.ts +1 -0
  38. package/templates/base/src/modules/auth/types/password.types.ts +1 -0
  39. package/templates/base/src/modules/common/pages/NotFound.tsx +14 -0
  40. package/templates/base/src/modules/common/pages/index.ts +1 -0
  41. package/templates/base/src/utils/api-error-handler.ts +25 -0
  42. package/templates/base/tsconfig.app.json +32 -0
  43. package/templates/base/tsconfig.json +13 -0
  44. package/templates/base/tsconfig.node.json +26 -0
  45. package/templates/base/vite-env.d.ts +1 -0
  46. package/templates/base/vite.config.ts +18 -0
  47. package/templates/hooks/index.ts +0 -0
  48. package/templates/hooks/useDebounce.ts +1 -0
  49. package/templates/hooks/useTheme.ts +1 -0
  50. package/templates/hooks/useThrottle.ts +1 -0
  51. package/templates/hooks/useWebStorage.ts +1 -0
  52. package/templates/router/react-router/src/components/ProtectedRoute.tsx +20 -0
  53. package/templates/router/react-router/src/components/PublicRoute.tsx +20 -0
  54. package/templates/router/react-router/src/modules/auth/routes/index.tsx +21 -0
  55. package/templates/router/react-router/src/routes/AppRoutes.tsx +18 -0
  56. package/templates/router/react-router/src/routes/index.ts +3 -0
  57. package/templates/router/tanstack-router/src/providers/TanstackRouterProvider.tsx +14 -0
  58. package/templates/router/tanstack-router/src/routes/__root.tsx +13 -0
  59. package/templates/router/tanstack-router/src/routes/_protected/index.tsx +10 -0
  60. package/templates/router/tanstack-router/src/routes/_protected.tsx +18 -0
  61. package/templates/router/tanstack-router/src/routes/_public/forgot-password.tsx +6 -0
  62. package/templates/router/tanstack-router/src/routes/_public/login.tsx +6 -0
  63. package/templates/router/tanstack-router/src/routes/_public/register.tsx +6 -0
  64. package/templates/router/tanstack-router/src/routes/_public.tsx +13 -0
  65. package/templates/state/react-query/src/hook/useAuth.ts +43 -0
  66. package/templates/state/react-query/src/provider/ReactQueryProvider.tsx +22 -0
  67. package/templates/state/react-query/src/provider/index.ts +1 -0
  68. package/templates/state/zustand/src/auth/useAuthStore.ts +29 -0
  69. package/templates/state/zustand/src/index.ts +2 -0
  70. package/templates/state/zustand/src/theme/useThemeStore.ts +27 -0
  71. package/templates/styles/css/src/404.css +101 -0
  72. package/templates/styles/css/src/main.css +70 -0
  73. package/templates/styles/css/src/variables.css +15 -0
  74. package/templates/styles/scss/src/404.scss +103 -0
  75. package/templates/styles/scss/src/_index.scss +2 -0
  76. package/templates/styles/scss/src/_mixins.scss +27 -0
  77. package/templates/styles/scss/src/_variables.scss +28 -0
  78. package/templates/styles/scss/src/main.scss +20 -0
  79. package/templates/styles/tailwind/config/_vite.config.ts +14 -0
  80. package/templates/styles/tailwind/src/404.css +98 -0
  81. package/templates/styles/tailwind/src/main.css +123 -0
  82. package/templates/ui/shadcn/src/components/ui/button.tsx +62 -0
@@ -0,0 +1,21 @@
1
+ import { Login, Register, ForgotPassword } from '../pages';
2
+
3
+ export const authRoutes = [
4
+ {
5
+ children: [
6
+ {
7
+ path: 'login',
8
+ element: <Login />
9
+ },
10
+ {
11
+ path: 'register',
12
+ element: <Register />
13
+ },
14
+ {
15
+ path: 'forgot-password',
16
+ element: <ForgotPassword />
17
+ }
18
+ // Edit or Add routes as needed
19
+ ]
20
+ }
21
+ ]
@@ -0,0 +1,18 @@
1
+ import { authRoutes } from '@/modules/auth/routes';
2
+ import { NotFound } from '@/modules/common/pages';
3
+ import { useRoutes } from 'react-router-dom';
4
+
5
+ // Exaxmple: Import feature routes here
6
+ // import { dashboardRoutes } from '@/features/dashboard/routes';
7
+
8
+ export function AppRoutes() {
9
+ return useRoutes([
10
+ // Spread feature routes here
11
+ ...authRoutes,
12
+ {
13
+ path: '*',
14
+ element: <NotFound />
15
+ }
16
+ // ...dashboardRoutes,
17
+ ]);
18
+ }
@@ -0,0 +1,3 @@
1
+ export * from './AppRoutes';
2
+ export * from '../components/ProtectedRoute';
3
+ export * from '../components/PublicRoute';
@@ -0,0 +1,14 @@
1
+ import { RouterProvider, createRouter } from '@tanstack/react-router'
2
+ import { routeTree } from '../routeTree.gen'
3
+
4
+ const router = createRouter({ routeTree })
5
+
6
+ declare module '@tanstack/react-router' {
7
+ interface Register {
8
+ router: typeof router
9
+ }
10
+ }
11
+
12
+ export function TanStackRouterProvider() {
13
+ return <RouterProvider router={router} />
14
+ }
@@ -0,0 +1,13 @@
1
+ import { NotFound } from '@/modules/common/pages';
2
+ import { createRootRoute, Outlet } from '@tanstack/react-router';
3
+ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
4
+
5
+ export const Route = createRootRoute({
6
+ component: () => (
7
+ <>
8
+ <Outlet />
9
+ <TanStackRouterDevtools />
10
+ </>
11
+ ),
12
+ notFoundComponent: () => <NotFound />,
13
+ });
@@ -0,0 +1,10 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+
3
+ export const Route = createFileRoute('/_protected/')({
4
+ // Check public files and do the same - this is only template
5
+ component: RouteComponent,
6
+ })
7
+
8
+ function RouteComponent() {
9
+ return <div>Page for authenticated users</div>
10
+ }
@@ -0,0 +1,18 @@
1
+ import { createFileRoute, redirect, Outlet } from '@tanstack/react-router';
2
+ import { useAuthStore } from '@/store';
3
+
4
+ export const Route = createFileRoute('/_protected')({
5
+ beforeLoad: ({ location }) => {
6
+ const isAuthenticated = useAuthStore.getState().isAuthenticated;
7
+
8
+ if (!isAuthenticated) {
9
+ throw redirect({
10
+ to: '/login',
11
+ search: {
12
+ redirect: location.href,
13
+ },
14
+ });
15
+ }
16
+ },
17
+ component: () => <Outlet />,
18
+ });
@@ -0,0 +1,6 @@
1
+ import { ForgotPassword } from '@/modules/auth/pages'
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+
4
+ export const Route = createFileRoute('/_public/forgot-password')({
5
+ component: () => <ForgotPassword />,
6
+ })
@@ -0,0 +1,6 @@
1
+ import { Login } from '@/modules/auth/pages'
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+
4
+ export const Route = createFileRoute('/_public/login')({
5
+ component: () => <Login />,
6
+ })
@@ -0,0 +1,6 @@
1
+ import { Register } from '@/modules/auth/pages'
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+
4
+ export const Route = createFileRoute('/_public/register')({
5
+ component: () => <Register />,
6
+ })
@@ -0,0 +1,13 @@
1
+ import { createFileRoute, redirect, Outlet } from '@tanstack/react-router';
2
+ import { useAuthStore } from '@/store';
3
+
4
+ export const Route = createFileRoute('/_public')({
5
+ beforeLoad: () => {
6
+ const isAuthenticated = useAuthStore.getState().isAuthenticated;
7
+
8
+ if (isAuthenticated) {
9
+ throw redirect({ to: '/' });
10
+ }
11
+ },
12
+ component: () => <Outlet />,
13
+ });
@@ -0,0 +1,43 @@
1
+ import { getAPIErrorMessage } from "@/utils/api-error-handler";
2
+ import { AuthService } from "../services"
3
+ import { useMutation } from '@tanstack/react-query';
4
+
5
+ export const useAuth = () => {
6
+ const login = useMutation({
7
+ mutationFn: AuthService.login,
8
+ onSuccess: (res) => {
9
+ // Handle mutation success
10
+ },
11
+ onError: (error) => {
12
+ const errorMessage = getAPIErrorMessage(error);
13
+ console.error(errorMessage)
14
+ // Display error message to user
15
+ },
16
+ });
17
+
18
+ const register = useMutation({
19
+ mutationFn: AuthService.register,
20
+ onSuccess: (res) => {
21
+ // Handle mutation success
22
+ },
23
+ onError: (error) => {
24
+ const errorMessage = getAPIErrorMessage(error);
25
+ console.error(errorMessage)
26
+ // Display error message to user
27
+ },
28
+ });
29
+
30
+ const logout = useMutation({
31
+ mutationFn: AuthService.logout,
32
+ onSuccess: (res) => {
33
+ // Handle mutation success
34
+ },
35
+ onError: (error) => {
36
+ const errorMessage = getAPIErrorMessage(error);
37
+ console.error(errorMessage)
38
+ // Display error message to user
39
+ },
40
+ });
41
+
42
+ return { login, register, logout }
43
+ }
@@ -0,0 +1,22 @@
1
+ import { useState } from "react";
2
+ import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
3
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
4
+
5
+ export function ReactQueryProvider({ children }: { children: React.ReactNode }) {
6
+ const [queryClient] = useState(() => new QueryClient({
7
+ defaultOptions: {
8
+ queries: {
9
+ refetchOnWindowFocus: false,
10
+ retry: 1,
11
+ staleTime: 5 * 1000,
12
+ },
13
+ },
14
+ }));
15
+
16
+ return (
17
+ <QueryClientProvider client={queryClient}>
18
+ {children}
19
+ <ReactQueryDevtools initialIsOpen={false} />
20
+ </QueryClientProvider>
21
+ );
22
+ }
@@ -0,0 +1 @@
1
+ export * from './ReactQueryProvider'
@@ -0,0 +1,29 @@
1
+ import { create } from 'zustand';
2
+
3
+ interface User {
4
+ id: string;
5
+ email: string;
6
+ name?: string;
7
+ }
8
+
9
+ interface AuthState {
10
+ user: User | null;
11
+ isAuthenticated: boolean;
12
+ setAuth: (user: User) => void;
13
+ clearAuth: () => void;
14
+ }
15
+
16
+ export const useAuthStore = create<AuthState>((set) => ({
17
+ user: null,
18
+ isAuthenticated: false,
19
+
20
+ setAuth: (user) => set({
21
+ user,
22
+ isAuthenticated: true
23
+ }),
24
+
25
+ clearAuth: () => set({
26
+ user: null,
27
+ isAuthenticated: false
28
+ }),
29
+ }));
@@ -0,0 +1,2 @@
1
+ export * from './theme/useThemeStore';
2
+ export * from './auth/useAuthStore';
@@ -0,0 +1,27 @@
1
+ import { create } from 'zustand';
2
+ import { persist, devtools } from 'zustand/middleware';
3
+
4
+ interface Theme {
5
+ theme: 'light' | 'dark';
6
+ setTheme: (theme: 'light' | 'dark') => void;
7
+ toggleTheme: () => void;
8
+ }
9
+
10
+ export const useThemeStore = create<Theme>()(
11
+ devtools(
12
+ persist((set) => ({
13
+ theme: 'light',
14
+ setTheme: (theme) => set({ theme }),
15
+ toggleTheme: () => set((state) => ({
16
+ theme: state.theme === 'light' ? 'dark' : 'light'
17
+ })),
18
+ }),
19
+ {
20
+ name: 'theme'
21
+ }
22
+ ),
23
+ {
24
+ name: 'ThemeStore'
25
+ }
26
+ )
27
+ )
@@ -0,0 +1,101 @@
1
+ @import "./variables.css";
2
+
3
+ .not-found-wrapper {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+ min-height: 100vh;
9
+ padding: 20px;
10
+ text-align: center;
11
+ font-family: var(--font-main);
12
+ background: var(--bg-light);
13
+ }
14
+
15
+ .not-found-content {
16
+ padding: 100px 70px;
17
+ background: var(--white);
18
+ max-width: 700px;
19
+ width: 100%;
20
+ display: flex;
21
+ flex-direction: column;
22
+ justify-content: center;
23
+ align-items: center;
24
+ border-radius: var(--radius-lg);
25
+ box-shadow: var(--shadow-main);
26
+ }
27
+
28
+ .not-found-content span {
29
+ color: var(--text-muted);
30
+ font-weight: 700;
31
+ font-size: 6rem;
32
+ line-height: 1;
33
+ }
34
+
35
+ .not-found-content h1 {
36
+ font-size: 2.5rem;
37
+ font-weight: 600;
38
+ margin: 0;
39
+ color: var(--text-dark);
40
+ }
41
+
42
+ .not-found-content p {
43
+ font-size: 1rem;
44
+ color: var(--text-muted);
45
+ max-width: 360px;
46
+ width: 100%;
47
+ margin: 10px 0;
48
+ }
49
+
50
+ .not-found-content a {
51
+ font-size: 0.9rem;
52
+ color: var(--white);
53
+ background-color: var(--primary);
54
+ padding: 10px 30px;
55
+ margin-top: 20px;
56
+ border-radius: var(--radius-sm);
57
+ transition: 0.2s;
58
+ cursor: pointer;
59
+ text-decoration: none;
60
+ display: inline-block;
61
+ }
62
+
63
+ .not-found-content a:hover {
64
+ background: var(--primary-hover);
65
+ }
66
+
67
+ @media (max-width: 768px) {
68
+ .not-found-content {
69
+ padding: 60px 40px;
70
+ max-width: 90%;
71
+ }
72
+ .not-found-content span {
73
+ font-size: 4.5rem;
74
+ margin-bottom: 20px;
75
+ }
76
+ .not-found-content h1 {
77
+ font-size: 2rem;
78
+ }
79
+ }
80
+
81
+ @media (max-width: 480px) {
82
+ .not-found-content {
83
+ padding: 40px 20px;
84
+ border-radius: var(--radius-md);
85
+ }
86
+ .not-found-content span {
87
+ font-size: 3.5rem;
88
+ margin-bottom: 20px;
89
+ }
90
+ .not-found-content h1 {
91
+ font-size: 1.5rem;
92
+ }
93
+ .not-found-content p {
94
+ font-size: 0.9rem;
95
+ }
96
+ .not-found-content a {
97
+ width: 100%;
98
+ box-sizing: border-box;
99
+ text-align: center;
100
+ }
101
+ }
@@ -0,0 +1,70 @@
1
+ @import "./variables.css";
2
+
3
+ * {
4
+ margin: 0;
5
+ padding: 0;
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ html {
10
+ scroll-behavior: smooth;
11
+ }
12
+
13
+ body {
14
+ font-family: var(--font-main);
15
+ background-color: var(--white);
16
+ color: var(--text-dark);
17
+ line-height: 1.6;
18
+ min-height: 100vh;
19
+ -webkit-font-smoothing: antialiased;
20
+ -moz-osx-font-smoothing: grayscale;
21
+ }
22
+
23
+ h1,
24
+ h2,
25
+ h3,
26
+ h4,
27
+ h5,
28
+ h6 {
29
+ color: var(--text-dark);
30
+ font-weight: 600;
31
+ line-height: 1.2;
32
+ }
33
+
34
+ p {
35
+ color: var(--text-muted);
36
+ }
37
+
38
+ .container {
39
+ width: 100%;
40
+ max-width: 1200px;
41
+ margin: 0 auto;
42
+ padding: 0 20px;
43
+ }
44
+
45
+ .flex-center {
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ }
50
+
51
+ a {
52
+ text-decoration: none;
53
+ color: var(--primary);
54
+ transition: 0.3s ease;
55
+ }
56
+
57
+ a:hover {
58
+ color: var(--primary-hover);
59
+ }
60
+
61
+ button {
62
+ font-family: inherit;
63
+ cursor: pointer;
64
+ }
65
+
66
+ img {
67
+ max-width: 100%;
68
+ height: auto;
69
+ display: block;
70
+ }
@@ -0,0 +1,15 @@
1
+ :root {
2
+ --primary: #37538a;
3
+ --primary-hover: #263c67;
4
+ --bg-light: #e6edfc;
5
+ --white: #ffffff;
6
+ --text-dark: #111111;
7
+ --text-muted: #666666;
8
+
9
+ --font-main: "Arial", sans-serif;
10
+
11
+ --shadow-main: 0px 0px 14px -14px rgba(0, 0, 0, 0.75);
12
+ --radius-lg: 24px;
13
+ --radius-md: 16px;
14
+ --radius-sm: 10px;
15
+ }
@@ -0,0 +1,103 @@
1
+ @use "./index.scss" as *;
2
+
3
+ .not-found-wrapper {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+ min-height: 100vh;
9
+ padding: 20px;
10
+ text-align: center;
11
+ font-family: $font-main;
12
+ background: $bg-light;
13
+
14
+ .not-found-content {
15
+ padding: 100px 70px;
16
+ background: $white;
17
+ max-width: 700px;
18
+ width: 100%;
19
+ display: flex;
20
+ flex-direction: column;
21
+ justify-content: center;
22
+ align-items: center;
23
+ border-radius: $radius-lg;
24
+ box-shadow: $shadow-main;
25
+
26
+ span {
27
+ color: $text-muted;
28
+ font-weight: 700;
29
+ font-size: 6rem;
30
+ line-height: 1;
31
+ }
32
+
33
+ h1 {
34
+ font-size: 2.5rem;
35
+ font-weight: 600;
36
+ margin: 0;
37
+ color: $text-dark;
38
+ }
39
+
40
+ p {
41
+ font-size: 1rem;
42
+ color: $text-muted;
43
+ max-width: 360px;
44
+ width: 100%;
45
+ margin: 10px 0;
46
+ }
47
+
48
+ a {
49
+ font-size: 0.9rem;
50
+ color: $white;
51
+ background-color: $primary;
52
+ padding: 10px 30px;
53
+ margin-top: 20px;
54
+ border-radius: $radius-sm;
55
+ transition: 0.2s;
56
+ cursor: pointer;
57
+ text-decoration: none;
58
+ display: inline-block;
59
+
60
+ &:hover {
61
+ background: $primary-hover;
62
+ }
63
+ }
64
+
65
+ @media (max-width: 768px) {
66
+ padding: 60px 40px;
67
+ max-width: 90%;
68
+
69
+ span {
70
+ font-size: 4.5rem;
71
+ margin-bottom: 20px;
72
+ }
73
+
74
+ h1 {
75
+ font-size: 2rem;
76
+ }
77
+ }
78
+
79
+ @media (max-width: 480px) {
80
+ padding: 40px 20px;
81
+ border-radius: $radius-md;
82
+
83
+ span {
84
+ font-size: 3.5rem;
85
+ margin-bottom: 20px;
86
+ }
87
+
88
+ h1 {
89
+ font-size: 1.5rem;
90
+ }
91
+
92
+ p {
93
+ font-size: 0.9rem;
94
+ }
95
+
96
+ a {
97
+ width: 100%;
98
+ box-sizing: border-box;
99
+ text-align: center;
100
+ }
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,2 @@
1
+ @forward "variables";
2
+ @forward "mixins";
@@ -0,0 +1,27 @@
1
+ $breakpoint-tablet: 768px;
2
+ $breakpoint-mobile: 480px;
3
+
4
+ @mixin tablet {
5
+ @media (max-width: #{$breakpoint-tablet}) {
6
+ @content;
7
+ }
8
+ }
9
+
10
+ @mixin mobile {
11
+ @media (max-width: #{$breakpoint-mobile}) {
12
+ @content;
13
+ }
14
+ }
15
+
16
+ // helpers
17
+ @mixin flex-center {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ }
22
+
23
+ @mixin text-truncate {
24
+ overflow: hidden;
25
+ text-overflow: ellipsis;
26
+ white-space: nowrap;
27
+ }
@@ -0,0 +1,28 @@
1
+ // Brand Colors
2
+ $primary: #37538a;
3
+ $primary-hover: #263c67;
4
+ $primary-dark: #263c67;
5
+ $accent: #e6edfc;
6
+
7
+ // Text
8
+ $text-dark: #111111;
9
+ $text-muted: #666666;
10
+
11
+ // Background
12
+ $bg-light: #e6edfc;
13
+
14
+ // Radius
15
+ $radius-sm: 10px;
16
+ $radius-md: 16px;
17
+ $radius-lg: 24px;
18
+
19
+ // Shadows
20
+ $shadow-main: 0px 0px 14px -14px rgba(0, 0, 0, 0.75);
21
+
22
+ // Neutrals
23
+ $white: #ffffff;
24
+ $black: #111111;
25
+ $gray: #666666;
26
+
27
+ // Fonts
28
+ $font-main: "Arial", sans-serif;
@@ -0,0 +1,20 @@
1
+ @use "index" as *;
2
+
3
+ * {
4
+ margin: 0;
5
+ padding: 0;
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ body {
10
+ font-family: $font-main;
11
+ background-color: $white;
12
+ color: $black;
13
+ line-height: 1.5;
14
+ -webkit-font-smoothing: antialiased;
15
+ }
16
+
17
+ a {
18
+ text-decoration: none;
19
+ color: inherit;
20
+ }
@@ -0,0 +1,14 @@
1
+ import path from "path"
2
+ import tailwindcss from "@tailwindcss/vite"
3
+ import react from "@vitejs/plugin-react"
4
+ import { defineConfig } from "vite"
5
+
6
+ // https://vite.dev/config/
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss()],
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(__dirname, "./src"),
12
+ },
13
+ },
14
+ })