diff --git a/frontend/src/app/brand-assets/page.tsx b/frontend/src/app/brand-assets/page.tsx index 2bd6ddb..fc7258e 100644 --- a/frontend/src/app/brand-assets/page.tsx +++ b/frontend/src/app/brand-assets/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; + import Hero from "@/components/BrandAssets/Hero"; import KlerosBadgesSection from "@/components/BrandAssets/KlerosBadgesSection"; import KlerosColorsSection from "@/components/BrandAssets/KlerosColorsSection/index"; @@ -36,6 +38,11 @@ import { StyledImagesSectionQueryType, } from "@/queries/brand-assets/styled-images-section"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("brandAssetsPageSeo"); +}; const BrandAssets: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/community/page.tsx b/frontend/src/app/community/page.tsx index fdca25a..5755954 100644 --- a/frontend/src/app/community/page.tsx +++ b/frontend/src/app/community/page.tsx @@ -1,7 +1,14 @@ +import type { Metadata } from "next"; + import CommunitiesSection from "@/components/Community/CommunitiesSection"; import Hero from "@/components/Community/hero"; import { heroQuery, HeroQueryType } from "@/queries/community/hero"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("communityPageSeo"); +}; const Community: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/cooperative/page.tsx b/frontend/src/app/cooperative/page.tsx index 9bcd6d4..dc49f6d 100644 --- a/frontend/src/app/cooperative/page.tsx +++ b/frontend/src/app/cooperative/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; + import Hero from "@/components/Cooperative/hero"; import MemberSection from "@/components/Cooperative/MemberSection"; import ReportSection from "@/components/Cooperative/ReportSection"; @@ -11,6 +13,11 @@ import { CooperativePageReportQueryType, } from "@/queries/cooperative/report-section"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("cooperativePageSeo"); +}; const Cooperative: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/earn/page.tsx b/frontend/src/app/earn/page.tsx index 5397d80..6e5236d 100644 --- a/frontend/src/app/earn/page.tsx +++ b/frontend/src/app/earn/page.tsx @@ -1,8 +1,15 @@ +import type { Metadata } from "next"; + import Hero from "@/components/Earn/Hero"; import TabSection from "@/components/Earn/TabSection"; import { heroQuery, HeroQueryType } from "@/queries/earn/hero"; import { tabSectionQuery, TabSectionQueryType } from "@/queries/earn/tabs-data"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("earnPageSeo"); +}; const Earn: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/for-builders/page.tsx b/frontend/src/app/for-builders/page.tsx index c07021b..c40186a 100644 --- a/frontend/src/app/for-builders/page.tsx +++ b/frontend/src/app/for-builders/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; + import Hero from "@/components/ForBuilders/Hero"; import UseCasesSection from "@/components/ForBuilders/UseCasesSection"; import IntegrateSection from "@/components/IntegrateSection"; @@ -7,6 +9,11 @@ import { UseCasesQueryType, } from "@/queries/for-builders/use-cases"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("forBuildersPageSeo"); +}; const ForBuilders: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/for-lawyers/page.tsx b/frontend/src/app/for-lawyers/page.tsx index e80beda..433e545 100644 --- a/frontend/src/app/for-lawyers/page.tsx +++ b/frontend/src/app/for-lawyers/page.tsx @@ -1,3 +1,7 @@ +import type { Metadata } from "next"; + +import { getPageMetadata } from "@/utils/seo"; + import Hero from "./components/Hero"; import KlerosDisputeResolutionSection from "./components/KlerosDisputeResolutionSection"; import KlerosEnterpriseSection from "./components/KlerosEnterpriseSection"; @@ -5,6 +9,10 @@ import KlerosFellowSection from "./components/KlerosFellowSection"; import KlerosMediationSection from "./components/KlerosMediationSection"; import KlerosParticipateSection from "./components/KlerosParticipateSection"; +export const generateMetadata = async (): Promise => { + return getPageMetadata("forLawyersPageSeo"); +}; + const ForLawyers: React.FC = async () => { return ( <> diff --git a/frontend/src/app/home/page.tsx b/frontend/src/app/home/page.tsx index e7e54dc..c2c6899 100644 --- a/frontend/src/app/home/page.tsx +++ b/frontend/src/app/home/page.tsx @@ -1,4 +1,7 @@ +import type { Metadata } from "next"; + import IntegrateSection from "@/components/IntegrateSection"; +import { getPageMetadata } from "@/utils/seo"; import CaseStudies from "./components/CaseStudies"; import GetInTouch from "./components/GetInTouch"; @@ -9,6 +12,10 @@ import StartEarning from "./components/StartEarning"; import TrustedBy from "./components/TrustedBy"; import UseCases from "./components/UseCases"; +export const generateMetadata = async (): Promise => { + return await getPageMetadata("homePageSeo"); +}; + const Home: React.FC = async () => { return ( <> diff --git a/frontend/src/app/icon.svg b/frontend/src/app/icon.svg new file mode 100644 index 0000000..cd36b61 --- /dev/null +++ b/frontend/src/app/icon.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 1d79f5b..5c3a260 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -5,11 +5,11 @@ import { Urbanist } from "next/font/google"; import Footer from "@/components/Footer"; import Navbar from "@/components/Navbar"; +import { HeroImagesQueryType, herosImagesQuery } from "@/queries/heroImages"; import { navbarQuery, NavbarQueryType } from "@/queries/navbar"; import "@/styles/globals.css"; import { getHeroImgsProps } from "@/utils/getHeroImgsProps"; import { request } from "@/utils/graphQLClient"; -import { HeroImagesQueryType, herosImagesQuery } from "@/queries/heroImages"; const urbanist = Urbanist({ weight: ["400", "500"], diff --git a/frontend/src/app/pnk-token/page.tsx b/frontend/src/app/pnk-token/page.tsx index 94d8e5a..aa75d2b 100644 --- a/frontend/src/app/pnk-token/page.tsx +++ b/frontend/src/app/pnk-token/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; + import BuySection from "@/components/PNKToken/BuySection"; import Hero from "@/components/PNKToken/Hero"; import TokenNeedSection from "@/components/PNKToken/TokenNeedSection"; @@ -16,6 +18,11 @@ import { tokenomicsSectionQuery, } from "@/queries/pnk-token/tokenomics"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return await getPageMetadata("pnkTokenPageSeo"); +}; const PNKToken: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/r-and-d/page.tsx b/frontend/src/app/r-and-d/page.tsx index b44f583..4e94c4f 100644 --- a/frontend/src/app/r-and-d/page.tsx +++ b/frontend/src/app/r-and-d/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; + import Hero from "@/components/ResearchDevelopment/Hero"; import TabSection from "@/components/ResearchDevelopment/TabSection"; import { heroQuery, HeroQueryType } from "@/queries/research-development/hero"; @@ -6,6 +8,11 @@ import { TabSectionQueryType, } from "@/queries/research-development/tabs-data"; import { request } from "@/utils/graphQLClient"; +import { getPageMetadata } from "@/utils/seo"; + +export const generateMetadata = async (): Promise => { + return getPageMetadata("rAndDPageSeo"); +}; const ResearchDevelopment: React.FC = async () => { const heroData = await request(heroQuery); diff --git a/frontend/src/app/robots.txt b/frontend/src/app/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/frontend/src/app/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/frontend/src/queries/seo.ts b/frontend/src/queries/seo.ts new file mode 100644 index 0000000..34c277e --- /dev/null +++ b/frontend/src/queries/seo.ts @@ -0,0 +1,65 @@ +import { gql } from "graphql-request"; + +const SEO_CONTENT = ` + SEO { + title + description + image { + url + } + } +`; + +export const seoQuery = gql` + { + brandAssetsPageSeo { + ${SEO_CONTENT} + } + communityPageSeo { + ${SEO_CONTENT} + } + cooperativePageSeo { + ${SEO_CONTENT} + } + earnPageSeo { + ${SEO_CONTENT} + } + forBuildersPageSeo { + ${SEO_CONTENT} + } + forLawyersPageSeo { + ${SEO_CONTENT} + } + homePageSeo { + ${SEO_CONTENT} + } + pnkTokenPageSeo { + ${SEO_CONTENT} + } + rAndDPageSeo { + ${SEO_CONTENT} + } + } +`; + +type ISEO = { + SEO: { + title: string; + description: string; + image: { + url: string; + }; + }; +}; + +export type SEOQueryType = { + brandAssetsPageSeo: ISEO; + communityPageSeo: ISEO; + cooperativePageSeo: ISEO; + earnPageSeo: ISEO; + forBuildersPageSeo: ISEO; + forLawyersPageSeo: ISEO; + homePageSeo: ISEO; + pnkTokenPageSeo: ISEO; + rAndDPageSeo: ISEO; +}; diff --git a/frontend/src/utils/seo.ts b/frontend/src/utils/seo.ts new file mode 100644 index 0000000..3c193ed --- /dev/null +++ b/frontend/src/utils/seo.ts @@ -0,0 +1,21 @@ +import type { Metadata } from "next"; + +import { seoQuery, SEOQueryType } from "@/queries/seo"; +import { request } from "@/utils/graphQLClient"; + +type PageKey = keyof SEOQueryType; + +export const getPageMetadata = async (pageKey: PageKey): Promise => { + const seoData = await request(seoQuery); + const { title, description, image } = seoData[pageKey].SEO; + + return { + title, + description, + openGraph: { + title, + description, + images: image.url, + }, + }; +};