create-fe-boilerplate 0.2.0 → 0.3.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 (51) hide show
  1. package/bin/index.js +52 -12
  2. package/package.json +11 -3
  3. package/templates/next/ts/tailwind/axios/README.md +36 -0
  4. package/templates/next/ts/tailwind/axios/eslint.config.mjs +18 -0
  5. package/templates/next/ts/tailwind/axios/next.config.ts +7 -0
  6. package/templates/next/ts/tailwind/axios/package-lock.json +6626 -0
  7. package/templates/next/ts/tailwind/axios/package.json +27 -0
  8. package/templates/next/ts/tailwind/axios/postcss.config.mjs +7 -0
  9. package/templates/next/ts/tailwind/axios/public/file.svg +1 -0
  10. package/templates/next/ts/tailwind/axios/public/globe.svg +1 -0
  11. package/templates/next/ts/tailwind/axios/public/next.svg +1 -0
  12. package/templates/next/ts/tailwind/axios/public/vercel.svg +1 -0
  13. package/templates/next/ts/tailwind/axios/public/window.svg +1 -0
  14. package/templates/next/ts/tailwind/axios/src/api/auth.ts +10 -0
  15. package/templates/next/ts/tailwind/axios/src/api/axios.ts +17 -0
  16. package/templates/next/ts/tailwind/axios/src/app/dashboard/page.tsx +32 -0
  17. package/templates/next/ts/tailwind/axios/src/app/favicon.ico +0 -0
  18. package/templates/next/ts/tailwind/axios/src/app/globals.css +26 -0
  19. package/templates/next/ts/tailwind/axios/src/app/layout.tsx +34 -0
  20. package/templates/next/ts/tailwind/axios/src/app/login/page.tsx +71 -0
  21. package/templates/next/ts/tailwind/axios/src/app/page.tsx +5 -0
  22. package/templates/next/ts/tailwind/axios/src/app/signup/page.tsx +56 -0
  23. package/templates/next/ts/tailwind/axios/src/components/AuthGuard.tsx +35 -0
  24. package/templates/next/ts/tailwind/axios/src/components/VerifyOtpModal.tsx +58 -0
  25. package/templates/next/ts/tailwind/axios/tsconfig.json +36 -0
  26. package/templates/react/js/tailwind/axios/vite.config.js +1 -1
  27. package/templates/react/js/tailwind/rtk/README.md +73 -0
  28. package/templates/react/js/tailwind/rtk/eslint.config.js +23 -0
  29. package/templates/react/js/tailwind/rtk/index.html +13 -0
  30. package/templates/react/js/tailwind/rtk/package-lock.json +4597 -0
  31. package/templates/react/js/tailwind/rtk/package.json +37 -0
  32. package/templates/react/js/tailwind/rtk/postcss.config.js +6 -0
  33. package/templates/react/js/tailwind/rtk/public/vite.svg +1 -0
  34. package/templates/react/js/tailwind/rtk/react-ts-tailwind-axios/.env.example +1 -0
  35. package/templates/react/js/tailwind/rtk/src/App.css +0 -0
  36. package/templates/react/js/tailwind/rtk/src/App.jsx +14 -0
  37. package/templates/react/js/tailwind/rtk/src/api/axios.ts +236 -0
  38. package/templates/react/js/tailwind/rtk/src/component/auth/VerifyOtpModal.jsx +60 -0
  39. package/templates/react/js/tailwind/rtk/src/component/common/ui/Toast/Toast.js +59 -0
  40. package/templates/react/js/tailwind/rtk/src/contants/constants.js +45 -0
  41. package/templates/react/js/tailwind/rtk/src/index.css +4 -0
  42. package/templates/react/js/tailwind/rtk/src/main.jsx +14 -0
  43. package/templates/react/js/tailwind/rtk/src/pages/Dashboard.jsx +10 -0
  44. package/templates/react/js/tailwind/rtk/src/pages/Login.jsx +69 -0
  45. package/templates/react/js/tailwind/rtk/src/pages/Signup.jsx +75 -0
  46. package/templates/react/js/tailwind/rtk/src/router/AppRoutes.jsx +19 -0
  47. package/templates/react/js/tailwind/rtk/src/store/index.js +10 -0
  48. package/templates/react/js/tailwind/rtk/src/store/services/api.js +34 -0
  49. package/templates/react/js/tailwind/rtk/src/utils/utils.ts +59 -0
  50. package/templates/react/js/tailwind/rtk/tailwind.config.js +8 -0
  51. package/templates/react/js/tailwind/rtk/vite.config.js +7 -0
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "axios",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "eslint"
10
+ },
11
+ "dependencies": {
12
+ "axios": "^1.13.2",
13
+ "next": "16.1.1",
14
+ "react": "19.2.3",
15
+ "react-dom": "19.2.3"
16
+ },
17
+ "devDependencies": {
18
+ "@tailwindcss/postcss": "^4",
19
+ "@types/node": "^20",
20
+ "@types/react": "^19",
21
+ "@types/react-dom": "^19",
22
+ "eslint": "^9",
23
+ "eslint-config-next": "16.1.1",
24
+ "tailwindcss": "^4",
25
+ "typescript": "^5"
26
+ }
27
+ }
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1 @@
1
+ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
@@ -0,0 +1,10 @@
1
+ import { axiosApi } from "./axios";
2
+
3
+ export const loginApi = (data: { email: string; password: string }) =>
4
+ axiosApi.post("/auth/login", data);
5
+
6
+ export const signupApi = (data: { email: string; password: string }) =>
7
+ axiosApi.post("/auth/signup", data);
8
+
9
+ export const verifyOtpApi = (data: { refId: string; otp: string }) =>
10
+ axiosApi.post("/auth/verify-otp", data);
@@ -0,0 +1,17 @@
1
+ import axios from "axios";
2
+
3
+ const BASE_URL = process.env.NEXT_PUBLIC_API_HOST;
4
+
5
+ export const axiosApi = axios.create({
6
+ baseURL: BASE_URL,
7
+ });
8
+
9
+ axiosApi.interceptors.request.use((config) => {
10
+ if (typeof window !== "undefined") {
11
+ const token = localStorage.getItem("token");
12
+ if (token) {
13
+ config.headers.Authorization = `Bearer ${token}`;
14
+ }
15
+ }
16
+ return config;
17
+ });
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import AuthGuard from "@/components/AuthGuard";
4
+ import { useRouter } from "next/navigation";
5
+
6
+ export default function DashboardPage() {
7
+ const router = useRouter();
8
+
9
+ const handleLogout = () => {
10
+ localStorage.removeItem("token");
11
+ router.replace("/login");
12
+ };
13
+
14
+ return (
15
+ <AuthGuard>
16
+ <div className="p-6">
17
+ <div className="flex justify-between items-center">
18
+ <h1 className="text-2xl font-bold">Dashboard</h1>
19
+
20
+ <button
21
+ onClick={handleLogout}
22
+ className="px-4 py-2 bg-red-600 text-white rounded"
23
+ >
24
+ Logout
25
+ </button>
26
+ </div>
27
+
28
+ <p className="mt-4 text-gray-600">Protected dashboard content</p>
29
+ </div>
30
+ </AuthGuard>
31
+ );
32
+ }
@@ -0,0 +1,26 @@
1
+ @import "tailwindcss";
2
+
3
+ :root {
4
+ --background: #ffffff;
5
+ --foreground: #171717;
6
+ }
7
+
8
+ @theme inline {
9
+ --color-background: var(--background);
10
+ --color-foreground: var(--foreground);
11
+ --font-sans: var(--font-geist-sans);
12
+ --font-mono: var(--font-geist-mono);
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ :root {
17
+ --background: #0a0a0a;
18
+ --foreground: #ededed;
19
+ }
20
+ }
21
+
22
+ body {
23
+ background: var(--background);
24
+ color: var(--foreground);
25
+ font-family: Arial, Helvetica, sans-serif;
26
+ }
@@ -0,0 +1,34 @@
1
+ import type { Metadata } from "next";
2
+ import { Geist, Geist_Mono } from "next/font/google";
3
+ import "./globals.css";
4
+
5
+ const geistSans = Geist({
6
+ variable: "--font-geist-sans",
7
+ subsets: ["latin"],
8
+ });
9
+
10
+ const geistMono = Geist_Mono({
11
+ variable: "--font-geist-mono",
12
+ subsets: ["latin"],
13
+ });
14
+
15
+ export const metadata: Metadata = {
16
+ title: "Create Next App",
17
+ description: "Generated by create next app",
18
+ };
19
+
20
+ export default function RootLayout({
21
+ children,
22
+ }: Readonly<{
23
+ children: React.ReactNode;
24
+ }>) {
25
+ return (
26
+ <html lang="en" suppressHydrationWarning>
27
+ <body
28
+ className={`${geistSans.variable} ${geistMono.variable} antialiased`}
29
+ >
30
+ {children}
31
+ </body>
32
+ </html>
33
+ );
34
+ }
@@ -0,0 +1,71 @@
1
+ "use client";
2
+
3
+ import { useRouter } from "next/navigation";
4
+ import { useState } from "react";
5
+ import VerifyOtpModal from "@/components/VerifyOtpModal";
6
+ import { loginApi } from "@/api/auth";
7
+
8
+ export default function LoginPage() {
9
+ const router = useRouter();
10
+ const [showOtp, setShowOtp] = useState(false);
11
+ const [refId, setRefId] = useState("");
12
+
13
+ const handleLogin = async () => {
14
+ // 🔴 simulate API response
15
+ // await loginApi({
16
+ // email: "",
17
+ // password: "",
18
+ // });
19
+
20
+ const requiresOtp = true;
21
+
22
+ if (requiresOtp) {
23
+ setRefId("ref-123");
24
+ setShowOtp(true);
25
+ return;
26
+ }
27
+
28
+ router.push("/dashboard");
29
+ };
30
+
31
+ return (
32
+ <>
33
+ <div className="min-h-screen flex items-center justify-center bg-gray-100">
34
+ <div className="w-96 p-6 bg-white shadow rounded">
35
+ <h2 className="text-xl font-bold mb-4 text-black">Login</h2>
36
+
37
+ <input className="border w-full p-2 mb-2" placeholder="Email" />
38
+ <input
39
+ className="border w-full p-2 mb-4"
40
+ placeholder="Password"
41
+ type="password"
42
+ />
43
+
44
+ <button
45
+ onClick={handleLogin}
46
+ className="w-full bg-blue-600 text-white py-2 rounded"
47
+ >
48
+ Login
49
+ </button>
50
+
51
+ <p
52
+ className="text-sm text-blue-600 mt-4 cursor-pointer"
53
+ onClick={() => router.push("/signup")}
54
+ >
55
+ Don’t have an account? Signup
56
+ </p>
57
+ </div>
58
+ </div>
59
+
60
+ <VerifyOtpModal
61
+ isOpen={showOtp}
62
+ refId={refId}
63
+ onClose={() => setShowOtp(false)}
64
+ onSuccess={(token) => {
65
+ localStorage.setItem("token", token);
66
+ router.push("/dashboard");
67
+ }}
68
+ />
69
+ </>
70
+ );
71
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from "next/navigation";
2
+
3
+ export default function Home() {
4
+ redirect("/login");
5
+ }
@@ -0,0 +1,56 @@
1
+ "use client";
2
+
3
+ import { useRouter } from "next/navigation";
4
+ import { useState } from "react";
5
+ import VerifyOtpModal from "@/components/VerifyOtpModal";
6
+
7
+ export default function SignupPage() {
8
+ const router = useRouter();
9
+ const [showOtp, setShowOtp] = useState(false);
10
+ const [refId, setRefId] = useState("");
11
+
12
+ const handleSignup = async () => {
13
+ setRefId("ref-456");
14
+ setShowOtp(true);
15
+ };
16
+
17
+ return (
18
+ <>
19
+ <div className="min-h-screen flex items-center justify-center bg-gray-100">
20
+ <div className="w-96 p-6 bg-white shadow rounded">
21
+ <h2 className="text-xl font-bold mb-4 text-black">Signup</h2>
22
+
23
+ <input className="border w-full p-2 mb-2" placeholder="Email" />
24
+ <input
25
+ className="border w-full p-2 mb-4"
26
+ placeholder="Password"
27
+ type="password"
28
+ />
29
+
30
+ <button
31
+ onClick={handleSignup}
32
+ className="w-full bg-blue-600 text-white py-2 rounded"
33
+ >
34
+ Signup
35
+ </button>
36
+ <p
37
+ className="text-sm text-blue-600 mt-4 cursor-pointer"
38
+ onClick={() => router.push("/login")}
39
+ >
40
+ Already have an Account? Login
41
+ </p>
42
+ </div>
43
+ </div>
44
+
45
+ <VerifyOtpModal
46
+ isOpen={showOtp}
47
+ refId={refId}
48
+ onClose={() => setShowOtp(false)}
49
+ onSuccess={(token) => {
50
+ localStorage.setItem("token", token);
51
+ router.push("/dashboard");
52
+ }}
53
+ />
54
+ </>
55
+ );
56
+ }
@@ -0,0 +1,35 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { useRouter } from "next/navigation";
5
+
6
+ interface AuthGuardProps {
7
+ children: React.ReactNode;
8
+ }
9
+
10
+ export default function AuthGuard({ children }: AuthGuardProps) {
11
+ const router = useRouter();
12
+ const [checking, setChecking] = useState(true);
13
+
14
+ useEffect(() => {
15
+ const token = localStorage.getItem("token");
16
+
17
+ if (!token) {
18
+ router.replace("/login");
19
+ return;
20
+ }
21
+
22
+ setChecking(false);
23
+ }, [router]);
24
+
25
+ // Prevent flicker
26
+ if (checking) {
27
+ return (
28
+ <div className="min-h-screen flex items-center justify-center">
29
+ <p className="text-gray-600">Checking authentication...</p>
30
+ </div>
31
+ );
32
+ }
33
+
34
+ return <>{children}</>;
35
+ }
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ interface VerifyOtpModalProps {
6
+ isOpen: boolean;
7
+ refId: string;
8
+ onClose: () => void;
9
+ onSuccess: (token: string) => void;
10
+ }
11
+
12
+ export default function VerifyOtpModal({
13
+ isOpen,
14
+ refId,
15
+ onClose,
16
+ onSuccess,
17
+ }: VerifyOtpModalProps) {
18
+ const [otp, setOtp] = useState("");
19
+
20
+ if (!isOpen) return null;
21
+
22
+ const handleVerify = async () => {
23
+ // 🔴 replace with axios call later
24
+ const fakeToken = "dummy-token";
25
+ onSuccess(fakeToken);
26
+ };
27
+
28
+ return (
29
+ <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
30
+ <div className="bg-white w-96 p-6 rounded shadow">
31
+ <h2 className="text-xl font-bold mb-4 text-black">Verify OTP</h2>
32
+
33
+ <input
34
+ className="border-1 border-gray-300 w-full p-2 mb-4 text-black"
35
+ placeholder="Enter OTP"
36
+ value={otp}
37
+ onChange={(e) => setOtp(e.target.value)}
38
+ />
39
+
40
+ <div className="flex justify-end gap-2">
41
+ <button
42
+ onClick={onClose}
43
+ className="px-4 py-2 border rounded text-black"
44
+ >
45
+ Cancel
46
+ </button>
47
+
48
+ <button
49
+ onClick={handleVerify}
50
+ className="px-4 py-2 bg-green-600 text-white rounded"
51
+ >
52
+ Verify
53
+ </button>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./src/*"]
23
+ },
24
+ "types": ["next", "react", "react-dom", "node"],
25
+ "typeRoots": ["./node_modules/@types"]
26
+ },
27
+ "include": [
28
+ "next-env.d.ts",
29
+ "**/*.ts",
30
+ "**/*.tsx",
31
+ ".next/types/**/*.ts",
32
+ ".next/dev/types/**/*.ts",
33
+ "**/*.mts"
34
+ ],
35
+ "exclude": ["node_modules"]
36
+ }
@@ -2,5 +2,5 @@ import { defineConfig } from "vite";
2
2
  import react from "@vitejs/plugin-react";
3
3
 
4
4
  export default defineConfig({
5
- plugins: [react()],
5
+ plugins: [react()]
6
6
  });
@@ -0,0 +1,73 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
+
18
+ ```js
19
+ export default defineConfig([
20
+ globalIgnores(['dist']),
21
+ {
22
+ files: ['**/*.{ts,tsx}'],
23
+ extends: [
24
+ // Other configs...
25
+
26
+ // Remove tseslint.configs.recommended and replace with this
27
+ tseslint.configs.recommendedTypeChecked,
28
+ // Alternatively, use this for stricter rules
29
+ tseslint.configs.strictTypeChecked,
30
+ // Optionally, add this for stylistic rules
31
+ tseslint.configs.stylisticTypeChecked,
32
+
33
+ // Other configs...
34
+ ],
35
+ languageOptions: {
36
+ parserOptions: {
37
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
+ tsconfigRootDir: import.meta.dirname,
39
+ },
40
+ // other options...
41
+ },
42
+ },
43
+ ])
44
+ ```
45
+
46
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
+
48
+ ```js
49
+ // eslint.config.js
50
+ import reactX from 'eslint-plugin-react-x'
51
+ import reactDom from 'eslint-plugin-react-dom'
52
+
53
+ export default defineConfig([
54
+ globalIgnores(['dist']),
55
+ {
56
+ files: ['**/*.{ts,tsx}'],
57
+ extends: [
58
+ // Other configs...
59
+ // Enable lint rules for React
60
+ reactX.configs['recommended-typescript'],
61
+ // Enable lint rules for React DOM
62
+ reactDom.configs.recommended,
63
+ ],
64
+ languageOptions: {
65
+ parserOptions: {
66
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
+ tsconfigRootDir: import.meta.dirname,
68
+ },
69
+ // other options...
70
+ },
71
+ },
72
+ ])
73
+ ```
@@ -0,0 +1,23 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+ import { defineConfig, globalIgnores } from 'eslint/config'
7
+
8
+ export default defineConfig([
9
+ globalIgnores(['dist']),
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ },
23
+ ])
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>react-ts-tailwind-axios</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.jsx"></script>
12
+ </body>
13
+ </html>