Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ export default function Home() {
</BlurFade>
</section>

{/* <HomeFAQSection /> */}
<section id="faq">
<BlurFade delay={0.2} inView>
<HomeFAQSection />
</BlurFade>
</section>

<section id="contact" className="flex flex-col snap-end">
<GetInTouchSections />
Expand Down
14 changes: 9 additions & 5 deletions src/app/(home)/sections/home-faq.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FaqSection } from "@components/ui/faq";
import FAQPageStructuredData from "@components/data-structured/faq-page";

export const HomeFAQSection = () => {
const data = [
Expand All @@ -17,10 +18,13 @@ export const HomeFAQSection = () => {
];

return (
<FaqSection
title="Frequently Asked Questions"
description="Everything about this projects."
items={data}
/>
<>
<FAQPageStructuredData items={data} />
<FaqSection
title="Frequently Asked Questions"
description="Everything about this projects."
items={data}
/>
</>
);
}
5 changes: 5 additions & 0 deletions src/app/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BlurFade } from '@components/ui/blur-fade';
import { Metadata } from "next";
import { appName, NEXT_PUBLIC_APP_URL } from "@lib/constants";
import AboutStructuredData from "@components/about-structured-data";
import BreadcrumbStructuredData from "@components/breadcrumb-structured-data";

const appPositions = ["I'm a Senior Front-end Developer", "and a Freelance UI/UX Designer."];
const description = `My name is <span className="text-primary font-semibold">Leat Sophat</span>, also known as <span className="text-primary font-semibold">PPhat</span>.
Expand Down Expand Up @@ -47,6 +48,10 @@ const AboutPage = () => {
return (
<main className="w-full flex flex-col gap-7 pb-5">
<AboutStructuredData />
<BreadcrumbStructuredData items={[
{ name: 'Home', url: NEXT_PUBLIC_APP_URL, position: 1 },
{ name: 'About', url: `${NEXT_PUBLIC_APP_URL}/about`, position: 2 },
]} />
<AboutMeHero description={description} appPositions={appPositions} />
<NavigationBar />

Expand Down
6 changes: 6 additions & 0 deletions src/app/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Image from 'next/image';
import "../../../styles/code-block-node.css"
import { GridPattern } from '@components/ui/grid-pattern';
import ArticleStructuredData from '@components/data-structured/article';
import BreadcrumbStructuredData from '@components/breadcrumb-structured-data';
import { MarkdownRenderer } from '@components/ui/markdown-renderer';
import { ScrollToTopButton } from '@components/ui/scroll-to-top-button';

Expand Down Expand Up @@ -111,6 +112,11 @@ export default async function PostDetail(props: Params) {
updatedAt={post.updatedAt}
content={post.content}
/>
<BreadcrumbStructuredData items={[
{ name: 'Home', url: NEXT_PUBLIC_APP_URL, position: 1 },
{ name: 'Posts', url: `${NEXT_PUBLIC_APP_URL}/posts`, position: 2 },
{ name: post.title, url: `${NEXT_PUBLIC_APP_URL}/posts/${post.slug}`, position: 3 },
]} />

<NavigationBar className='fixed' />
<div className="absolute inset-y-0 left-0 right-0 pointer-events-none opacity-60" aria-hidden="true">
Expand Down
13 changes: 12 additions & 1 deletion src/app/posts/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React from 'react';
import { Metadata } from 'next';
import postsMeta from '@lib/meta/posts';
import BreadcrumbStructuredData from '@components/breadcrumb-structured-data';
import { NEXT_PUBLIC_APP_URL } from '@lib/constants';

export const metadata: Metadata = {
...postsMeta,
Expand All @@ -13,5 +16,13 @@ export const metadata: Metadata = {
export default function PostsLayout({ children, }: {
children: React.ReactNode;
}) {
return (<> {children} </>);
return (
<>
<BreadcrumbStructuredData items={[
{ name: 'Home', url: NEXT_PUBLIC_APP_URL, position: 1 },
{ name: 'Posts', url: `${NEXT_PUBLIC_APP_URL}/posts`, position: 2 },
]} />
{children}
</>
);
}
13 changes: 12 additions & 1 deletion src/app/projects/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import React from 'react';
import { Metadata } from 'next';
import { projectsMeta } from '@lib/meta/projects';
import BreadcrumbStructuredData from '@components/breadcrumb-structured-data';
import { NEXT_PUBLIC_APP_URL } from '@lib/constants';

export const metadata: Metadata = projectsMeta;

export default function ProjectsLayout({ children, }: {
children: React.ReactNode;
}) {
return (<> {children} </>);
return (
<>
<BreadcrumbStructuredData items={[
{ name: 'Home', url: NEXT_PUBLIC_APP_URL, position: 1 },
{ name: 'Projects', url: `${NEXT_PUBLIC_APP_URL}/projects`, position: 2 },
]} />
{children}
</>
);
}
14 changes: 9 additions & 5 deletions src/components/about-structured-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ import {
export default function AboutStructuredData() {
const structuredData = {
"@context": "https://schema.org",
"@type": "AboutPage",
"@type": "ProfilePage",
"@id": `${NEXT_PUBLIC_APP_URL}/about`,
"name": `About ${appName}`,
"description": `I'm ${PERSON_NAME} (${PERSON_ALTERNATE_NAME}), a ${PERSON_JOB_TITLE}.`,
"url": `${NEXT_PUBLIC_APP_URL}/about`,
"dateCreated": "2021-01-01",
"dateModified": new Date().toISOString().split('T')[0],
"mainEntity": {
"@type": "Person",
"@id": `${NEXT_PUBLIC_APP_URL}#person`,
"name": PERSON_NAME,
"alternateName": PERSON_ALTERNATE_NAME,
"description": `I'm ${PERSON_NAME} (${PERSON_ALTERNATE_NAME}), a ${PERSON_JOB_TITLE}.`,
Expand All @@ -29,10 +36,7 @@ export default function AboutStructuredData() {
GITHUB_URL,
LINKEDIN_URL
]
},
"name": `About ${appName}`,
"description": `I'm ${PERSON_NAME} (${PERSON_ALTERNATE_NAME}), a ${PERSON_JOB_TITLE}.`,
"url": `${NEXT_PUBLIC_APP_URL}/about`
}
};

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/data-structured/article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function ArticleStructuredData({

const structuredData = {
"@context": "https://schema.org",
"@type": "Article",
"@type": "BlogPosting",
"@id": `${NEXT_PUBLIC_APP_URL}/posts/${slug}`,
"headline": title,
"description": description,
Expand Down
32 changes: 32 additions & 0 deletions src/components/data-structured/faq-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

interface FAQItem {
question: string;
answer: string;
}

interface FAQPageStructuredDataProps {
items: FAQItem[];
}

export default function FAQPageStructuredData({ items }: FAQPageStructuredDataProps) {
const structuredData = {
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": items.map((item) => ({
"@type": "Question",
"name": item.question,
"acceptedAnswer": {
"@type": "Answer",
"text": item.answer
}
}))
};

return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
);
}
72 changes: 72 additions & 0 deletions src/components/data-structured/software-application.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { NEXT_PUBLIC_APP_URL, PERSON_NAME, appName } from '@lib/constants';

interface SoftwareApplicationStructuredDataProps {
name: string;
description: string;
url: string;
repositoryUrl?: string;
applicationCategory?: string;
operatingSystem?: string;
screenshots?: string[];
datePublished?: string;
keywords?: string[];
}

export default function SoftwareApplicationStructuredData({
name,
description,
url,
repositoryUrl,
applicationCategory = 'WebApplication',
operatingSystem = 'Web Browser',
screenshots = [],
datePublished,
keywords = []
}: SoftwareApplicationStructuredDataProps) {
const structuredData = {
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": name,
"description": description,
"url": url,
"applicationCategory": applicationCategory,
"operatingSystem": operatingSystem,
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"author": {
"@type": "Person",
"@id": `${NEXT_PUBLIC_APP_URL}#person`,
"name": PERSON_NAME
},
"creator": {
"@type": "Person",
"@id": `${NEXT_PUBLIC_APP_URL}#person`,
"name": PERSON_NAME
},
"publisher": {
"@type": "Person",
"name": appName,
"url": NEXT_PUBLIC_APP_URL
},
...(datePublished && { "datePublished": datePublished }),
...(keywords.length > 0 && { "keywords": keywords.join(', ') }),
...(repositoryUrl && { "codeRepository": repositoryUrl }),
...(screenshots.length > 0 && {
"screenshot": screenshots.map(src => ({
"@type": "ImageObject",
"url": src.startsWith('http') ? src : `${NEXT_PUBLIC_APP_URL}${src}`
}))
})
};

return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
);
}