feat: add react helmet
This commit is contained in:
		
							parent
							
								
									5c4dc7244f
								
							
						
					
					
						commit
						a13603046c
					
				| @ -15,6 +15,7 @@ | ||||
|     "pixi.js": "^7.3.3", | ||||
|     "react": "^18.2.0", | ||||
|     "react-dom": "^18.2.0", | ||||
|     "react-helmet": "^6.1.0", | ||||
|     "react-router-dom": "^6.21.1", | ||||
|     "react-toastify": "^9.1.3", | ||||
|     "tailwind-merge": "^2.2.0" | ||||
| @ -24,6 +25,7 @@ | ||||
|     "@types/node": "^20.10.6", | ||||
|     "@types/react": "^18.2.43", | ||||
|     "@types/react-dom": "^18.2.17", | ||||
|     "@types/react-helmet": "^6.1.11", | ||||
|     "@typescript-eslint/eslint-plugin": "^6.14.0", | ||||
|     "@typescript-eslint/parser": "^6.14.0", | ||||
|     "@vitejs/plugin-react": "^4.2.1", | ||||
|  | ||||
| @ -2,20 +2,22 @@ import { lazy } from "react"; | ||||
| import { RouterProvider, createBrowserRouter } from "react-router-dom"; | ||||
| import MainLayout from "./components/layouts/MainLayout"; | ||||
| import ErrorBoundaryPage from "./pages/errors/error-boundary/page"; | ||||
| import NotFoundPage from "./pages/errors/not-found/page"; | ||||
| 
 | ||||
| const HomePage = lazy(() => import("./pages/home/page")); | ||||
| const FurinaBelovedPage = lazy(() => import("./pages/furina-beloved/page")); | ||||
| const MyFurinaPage = lazy(() => import("./pages/my-furina/page")); | ||||
| 
 | ||||
| const router = createBrowserRouter([ | ||||
|   { | ||||
|     Component: MainLayout, | ||||
|     children: [ | ||||
|       { index: true, Component: HomePage }, | ||||
|       { path: "/furina-beloved", Component: FurinaBelovedPage }, | ||||
|       { path: "*", Component: NotFoundPage }, | ||||
|       { path: "/toodle", Component: MyFurinaPage }, | ||||
|     ], | ||||
|     ErrorBoundary: ErrorBoundaryPage, | ||||
|     ErrorBoundary: () => ( | ||||
|       <MainLayout> | ||||
|         <ErrorBoundaryPage /> | ||||
|       </MainLayout> | ||||
|     ), | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
|  | ||||
| @ -24,7 +24,7 @@ const AppBar = () => { | ||||
| 
 | ||||
|         <Navbar> | ||||
|           <NavbarItem path="/" title="Pet the Furina" /> | ||||
|           <NavbarItem path="/furina-beloved" title="Shrimp" /> | ||||
|           <NavbarItem path="/toodle" title="Toodle-oo~" /> | ||||
|         </Navbar> | ||||
|       </div> | ||||
|     </header> | ||||
|  | ||||
							
								
								
									
										37
									
								
								src/components/containers/PageMetadata.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/components/containers/PageMetadata.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| import Helmet from "react-helmet"; | ||||
| 
 | ||||
| type PageMetadataProps = { | ||||
|   title?: string; | ||||
|   description?: string; | ||||
|   keywords?: string; | ||||
|   allowIndex?: boolean; | ||||
| }; | ||||
| 
 | ||||
| const PageMetadata = (props: PageMetadataProps) => { | ||||
|   return ( | ||||
|     <Helmet> | ||||
|       <title>{[props.title, "Furina.id"].filter((i) => !!i).join(" - ")}</title> | ||||
|       <meta | ||||
|         name="description" | ||||
|         content={props.description || "Welcome to Furina.id"} | ||||
|       /> | ||||
|       <meta | ||||
|         name="keywords" | ||||
|         content={[ | ||||
|           props.keywords, | ||||
|           "furina.id, furina build, furina gameplay, furina guide, furina genshin", | ||||
|         ] | ||||
|           .filter((i) => !!i) | ||||
|           .join(", ")} | ||||
|       /> | ||||
|       <meta | ||||
|         name="robots" | ||||
|         content={ | ||||
|           props.allowIndex !== false ? "index, follow" : "noindex, nofollow" | ||||
|         } | ||||
|       /> | ||||
|     </Helmet> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| export default PageMetadata; | ||||
| @ -1,13 +1,25 @@ | ||||
| import MainLayout from "@/components/layouts/MainLayout"; | ||||
| import { isRouteErrorResponse, useRouteError } from "react-router-dom"; | ||||
| import NotFoundPage from "../not-found/page"; | ||||
| import PageMetadata from "@/components/containers/PageMetadata"; | ||||
| 
 | ||||
| const ErrorBoundaryPage = () => { | ||||
|   const error = useRouteError(); | ||||
| 
 | ||||
|   if (isRouteErrorResponse(error)) { | ||||
|     if (error.status === 404) { | ||||
|       return <NotFoundPage />; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <MainLayout> | ||||
|     <> | ||||
|       <PageMetadata title="400 Bad Request" allowIndex={false} /> | ||||
| 
 | ||||
|       <div className="min-h-[80vh] flex flex-col items-center justify-center text-center"> | ||||
|         <h1 className="text-3xl font-medium">400 Bad Request.</h1> | ||||
|         <p className="mt-4">I think something is wrong here UwU</p> | ||||
|       </div> | ||||
|     </MainLayout> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -1,9 +1,15 @@ | ||||
| import PageMetadata from "@/components/containers/PageMetadata"; | ||||
| 
 | ||||
| const NotFoundPage = () => { | ||||
|   return ( | ||||
|     <div className="min-h-[80vh] flex flex-col items-center justify-center text-center"> | ||||
|       <h1 className="text-3xl font-medium">404 Page Not Found.</h1> | ||||
|       <p className="mt-4">I think something is missing here UwU</p> | ||||
|     </div> | ||||
|     <> | ||||
|       <PageMetadata title="404 Not Found" allowIndex={false} /> | ||||
| 
 | ||||
|       <div className="min-h-[80vh] flex flex-col items-center justify-center text-center"> | ||||
|         <h1 className="text-3xl font-medium">404 Page Not Found.</h1> | ||||
|         <p className="mt-4">I think something is missing here UwU</p> | ||||
|       </div> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react"; | ||||
| import styles from "./style.module.css"; | ||||
| import { cn } from "@/utility/utils"; | ||||
| import LoadingPage from "../misc/loading-page"; | ||||
| import PageMetadata from "@/components/containers/PageMetadata"; | ||||
| 
 | ||||
| const HomePage = () => { | ||||
|   const appRef = useRef<any>(); | ||||
| @ -36,6 +37,12 @@ const HomePage = () => { | ||||
| 
 | ||||
|   return ( | ||||
|     <div> | ||||
|       <PageMetadata | ||||
|         title="Pet the Furina" | ||||
|         description="Play pet the furina meme game" | ||||
|         keywords="pet furina, pet the furina, pet the meme, furina pat pat, pat furina" | ||||
|       /> | ||||
| 
 | ||||
|       {!isReady ? <LoadingPage /> : null} | ||||
| 
 | ||||
|       <div | ||||
|  | ||||
| @ -8,6 +8,7 @@ import skillAudio from "@/assets/audio/VO_JA_Furina_Elemental_Skill_1_04.ogg"; | ||||
| import { cn, copyToClipboard, showToast } from "@/utility/utils"; | ||||
| import { useEffect, useRef, useState } from "react"; | ||||
| import styles from "./style.module.css"; | ||||
| import PageMetadata from "@/components/containers/PageMetadata"; | ||||
| 
 | ||||
| const gameUID = "828243224"; | ||||
| 
 | ||||
| @ -19,6 +20,12 @@ const FurinaBelovedPage = () => { | ||||
| 
 | ||||
|   return ( | ||||
|     <div> | ||||
|       <PageMetadata | ||||
|         title="Toodle" | ||||
|         description="Eclair's Furina Build" | ||||
|         keywords="eclair, khairul, furina toodle" | ||||
|       /> | ||||
| 
 | ||||
|       <section> | ||||
|         <HeroBackground /> | ||||
| 
 | ||||
							
								
								
									
										45
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								yarn.lock
									
									
									
									
									
								
							| @ -833,6 +833,13 @@ | ||||
|   dependencies: | ||||
|     "@types/react" "*" | ||||
| 
 | ||||
| "@types/react-helmet@^6.1.11": | ||||
|   version "6.1.11" | ||||
|   resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.11.tgz#8cafcafff38f75361f451563ba7b406b0c5d3907" | ||||
|   integrity sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g== | ||||
|   dependencies: | ||||
|     "@types/react" "*" | ||||
| 
 | ||||
| "@types/react@*", "@types/react@^18.2.43": | ||||
|   version "18.2.46" | ||||
|   resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.46.tgz#f04d6c528f8f136ea66333bc66abcae46e2680df" | ||||
| @ -1827,7 +1834,7 @@ lodash.merge@^4.6.2: | ||||
|   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" | ||||
|   integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== | ||||
| 
 | ||||
| loose-envify@^1.1.0: | ||||
| loose-envify@^1.1.0, loose-envify@^1.4.0: | ||||
|   version "1.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" | ||||
|   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== | ||||
| @ -1924,7 +1931,7 @@ normalize-range@^0.1.2: | ||||
|   resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" | ||||
|   integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== | ||||
| 
 | ||||
| object-assign@^4.0.1: | ||||
| object-assign@^4.0.1, object-assign@^4.1.1: | ||||
|   version "4.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" | ||||
|   integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== | ||||
| @ -2126,6 +2133,15 @@ prelude-ls@^1.2.1: | ||||
|   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" | ||||
|   integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== | ||||
| 
 | ||||
| prop-types@^15.7.2: | ||||
|   version "15.8.1" | ||||
|   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" | ||||
|   integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== | ||||
|   dependencies: | ||||
|     loose-envify "^1.4.0" | ||||
|     object-assign "^4.1.1" | ||||
|     react-is "^16.13.1" | ||||
| 
 | ||||
| punycode@^1.4.1: | ||||
|   version "1.4.1" | ||||
|   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" | ||||
| @ -2156,6 +2172,26 @@ react-dom@^18.2.0: | ||||
|     loose-envify "^1.1.0" | ||||
|     scheduler "^0.23.0" | ||||
| 
 | ||||
| react-fast-compare@^3.1.1: | ||||
|   version "3.2.2" | ||||
|   resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" | ||||
|   integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== | ||||
| 
 | ||||
| react-helmet@^6.1.0: | ||||
|   version "6.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" | ||||
|   integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== | ||||
|   dependencies: | ||||
|     object-assign "^4.1.1" | ||||
|     prop-types "^15.7.2" | ||||
|     react-fast-compare "^3.1.1" | ||||
|     react-side-effect "^2.1.0" | ||||
| 
 | ||||
| react-is@^16.13.1: | ||||
|   version "16.13.1" | ||||
|   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" | ||||
|   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== | ||||
| 
 | ||||
| react-refresh@^0.14.0: | ||||
|   version "0.14.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" | ||||
| @ -2176,6 +2212,11 @@ react-router@6.21.1: | ||||
|   dependencies: | ||||
|     "@remix-run/router" "1.14.1" | ||||
| 
 | ||||
| react-side-effect@^2.1.0: | ||||
|   version "2.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.2.tgz#dc6345b9e8f9906dc2eeb68700b615e0b4fe752a" | ||||
|   integrity sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw== | ||||
| 
 | ||||
| react-toastify@^9.1.3: | ||||
|   version "9.1.3" | ||||
|   resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-9.1.3.tgz#1e798d260d606f50e0fab5ee31daaae1d628c5ff" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user