diff --git a/src/app/AppBody.tsx b/src/app/AppBody.tsx
new file mode 100644
index 0000000..b2b21d2
--- /dev/null
+++ b/src/app/AppBody.tsx
@@ -0,0 +1,46 @@
+import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles'
+import CssBaseline from '@mui/material/CssBaseline'
+import theme from '@Modules/theme'
+import '@Styles/globals.css'
+import { SpeedInsights } from '@vercel/speed-insights/next'
+
+import { StateProvider } from '@Modules/store'
+import { GoogleAnalytics } from '@Components/GoogleAnalytics'
+import SearchAppBar from '@Components/SearchAppBar/SearchAppBar'
+import Footer from '@Components/Footer'
+const Layout = ({ children }) => (
+
+ {children}
+
+)
+
+const Content = ({ children }) => {
+ return {children}
+}
+
+export const AppBody = ({ children }: { children: React.ReactNode }) => {
+ return (
+ <>
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 0000000..e635eee
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,19 @@
+import '@Styles/globals.css'
+import { AppBody } from '@App/AppBody'
+import { siteMetadata } from '@Modules/metadata'
+
+export const metadata = siteMetadata
+
+export default function RootLayout({
+ children
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+
+ {children}
+
+
+ )
+}
diff --git a/src/components/GoogleAnalytics.js b/src/components/GoogleAnalytics.js
new file mode 100644
index 0000000..eb9bf97
--- /dev/null
+++ b/src/components/GoogleAnalytics.js
@@ -0,0 +1,24 @@
+'use client';
+
+import ReactGA from 'react-ga'
+import { useEffect } from 'react'
+
+export const initGA = () => {
+ ReactGA.initialize('UA-35322373-3', { debug: false })
+}
+
+export const logPageView = () => {
+ ReactGA.set({ page: window.location.pathname })
+ ReactGA.pageview(window.location.pathname)
+}
+
+export const GoogleAnalytics = () => {
+ useEffect(() => {
+ if (!window.GA_INITIALIZED) {
+ initGA()
+ window.GA_INITIALIZED = true
+ }
+ logPageView()
+ })
+ return null
+}
diff --git a/src/components/StandardSeo.js b/src/components/StandardSeo.js
index 59f93b1..366790e 100644
--- a/src/components/StandardSeo.js
+++ b/src/components/StandardSeo.js
@@ -2,6 +2,9 @@ import { NextSeo } from 'next-seo'
const SITE_ROOT = 'https://bluprince13.com'
+/**
+ * @deprecated Use generateMetadata instead.
+ */
const StandardSeo = ({ pageTitle, description, path, bannerPath }) => {
const title = `${pageTitle} - Vipin Ajayakumar`
const url = `${SITE_ROOT}${path}`
diff --git a/src/modules/googleAnalytics.js b/src/modules/googleAnalytics.js
deleted file mode 100644
index 368b81c..0000000
--- a/src/modules/googleAnalytics.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import ReactGA from 'react-ga'
-
-export const initGA = () => {
- ReactGA.initialize('UA-35322373-3', { debug: false })
-}
-
-export const logPageView = () => {
- ReactGA.set({ page: window.location.pathname })
- ReactGA.pageview(window.location.pathname)
-}
diff --git a/src/modules/metadata.ts b/src/modules/metadata.ts
new file mode 100644
index 0000000..a2a1fd0
--- /dev/null
+++ b/src/modules/metadata.ts
@@ -0,0 +1,78 @@
+import { Metadata } from 'next'
+
+const SITE_ROOT = 'https://bluprince13.com'
+const title = 'bluprince13'
+const description = 'Full-stack web developer'
+
+export const siteMetadata: Metadata = {
+ title,
+ description,
+ alternates: {
+ canonical: SITE_ROOT,
+ // TODO: Support multiple RSS feeds
+ // https://github.com/vercel/next.js/discussions/62365
+ types: {
+ 'application/rss+xml': `${SITE_ROOT}/feed.xml`
+ }
+ },
+ openGraph: {
+ type: 'website',
+ locale: 'en_GB',
+ url: SITE_ROOT,
+ title,
+ description,
+ images: [
+ {
+ url: `${SITE_ROOT}/photo.jpg`,
+ alt: title
+ }
+ ]
+ },
+ twitter: {
+ creator: '@vipinajayakumar',
+ site: '@vipinajayakumar',
+ card: 'summary_large_image'
+ }
+}
+
+interface MetadataProps {
+ pageTitle: string
+ description: string
+ path: string
+ bannerPath?: string
+}
+
+export const generateMetadata = ({
+ pageTitle,
+ description,
+ path,
+ bannerPath
+}: MetadataProps): Metadata => {
+ const title = `${pageTitle} - Vipin Ajayakumar`
+ const url = `${SITE_ROOT}${path}`
+ const featuredImage = bannerPath ? `${SITE_ROOT}${bannerPath}` : null
+
+ return {
+ title,
+ description,
+ openGraph: {
+ url,
+ title,
+ description,
+ images: featuredImage
+ ? [
+ {
+ url: featuredImage,
+ alt: title
+ }
+ ]
+ : []
+ },
+ twitter: {
+ card: 'summary_large_image',
+ title,
+ description,
+ images: featuredImage ? [featuredImage] : []
+ }
+ }
+}
diff --git a/src/pages/_app.js b/src/pages/_app.js
index ad8072c..25124d1 100644
--- a/src/pages/_app.js
+++ b/src/pages/_app.js
@@ -1,46 +1,12 @@
-import { useEffect } from 'react'
import Head from 'next/head'
+import { useEffect } from 'react'
import { DefaultSeo } from 'next-seo'
-
-import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
-import CssBaseline from '@mui/material/CssBaseline'
-import theme from '@Modules/theme'
import '@Styles/globals.css'
-import { SpeedInsights } from '@vercel/speed-insights/next'
-
-import { StateProvider } from '@Modules/store'
-import { initGA, logPageView } from '@Modules/googleAnalytics'
-import SearchAppBar from '@Components/SearchAppBar/SearchAppBar'
-import Footer from '@Components/Footer'
+import { AppBody } from 'src/app/AppBody'
import SEO from '@Modules/seo.config'
-const Layout = ({ children }) => (
-
- {children}
-
-)
-
-const Content = ({ children }) => {
- return {children}
-}
-
function MyApp({ Component, pageProps }) {
useEffect(() => {
- if (!window.GA_INITIALIZED) {
- initGA()
- window.GA_INITIALIZED = true
- }
- logPageView()
- })
-
- useEffect(() => {
- // Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side')
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles)
@@ -75,21 +41,9 @@ function MyApp({ Component, pageProps }) {
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
>
)
}