feat: add schema.org metadata

This commit is contained in:
Riccardo
2024-08-31 19:40:32 +02:00
parent 8d23e1017f
commit 16d35b60b1
5 changed files with 92 additions and 28 deletions

View File

@@ -1,6 +1,8 @@
'use client'; 'use client';
import { CardDescription } from '@components/Card'; import { CardDescription } from '@components/Card';
import CustomCard from '@components/CustomCard'; import CustomCard from '@components/CustomCard';
import Schema from '@components/SchemaOrg';
import { ResponseType } from '@utils/validationSchemas'; import { ResponseType } from '@utils/validationSchemas';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import { Suspense, useEffect, useState } from 'react'; import { Suspense, useEffect, useState } from 'react';
@@ -54,7 +56,7 @@ function ConfirmationPage() {
fetchData(); fetchData();
}, [code, router]); }, [code, router]);
function render() { const renderContent = () => {
if (!loading) { if (!loading) {
return ( return (
<CardDescription className='text-center'>{message}</CardDescription> <CardDescription className='text-center'>{message}</CardDescription>
@@ -62,22 +64,33 @@ function ConfirmationPage() {
} }
return 'Just a second...'; return 'Just a second...';
} };
return ( return (
<CustomCard <CustomCard
className='max-90vw w-96' className='max-90vw w-96'
title={loading ? 'Verifying' : 'Confirmed!'} title={loading ? 'Verifying' : 'Confirmed!'}
content={render()} content={renderContent()}
footer={false} footer={false}
/> />
); );
} }
export default function Confirmation() { export default function Confirmation() {
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'HackerNews Newsletter',
title: 'Subscription Confirmation',
url: `${process.env.HOME_URL}/confirmation`
};
return ( return (
<Suspense fallback={<>Loading...</>}> <>
<ConfirmationPage /> <Schema schema={schema} />
</Suspense> <Suspense fallback={<>Loading...</>}>
<ConfirmationPage />
</Suspense>
</>
); );
} }

View File

@@ -1,4 +1,5 @@
'use client'; 'use client';
import { Button } from '@components/Button'; import { Button } from '@components/Button';
import { CardDescription } from '@components/Card'; import { CardDescription } from '@components/Card';
import CustomCard from '@components/CustomCard'; import CustomCard from '@components/CustomCard';
@@ -6,6 +7,7 @@ import ErrorMessage from '@components/ErrorMessage';
import { FormControl } from '@components/form/FormControl'; import { FormControl } from '@components/form/FormControl';
import { FormMessage } from '@components/form/FormMessage'; import { FormMessage } from '@components/form/FormMessage';
import { Input } from '@components/Input'; import { Input } from '@components/Input';
import Schema from '@components/SchemaOrg';
import { FormField } from '@contexts/FormField/FormFieldProvider'; import { FormField } from '@contexts/FormField/FormFieldProvider';
import { FormItem } from '@contexts/FormItem/FormItemProvider'; import { FormItem } from '@contexts/FormItem/FormItemProvider';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
@@ -22,6 +24,14 @@ export default function Home() {
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [error, setError] = useState(false); const [error, setError] = useState(false);
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'HackerNews Newsletter',
title: 'Home',
url: process.env.HOME_URL
};
const form = useForm<SubscribeFormType>({ const form = useForm<SubscribeFormType>({
resolver: zodResolver(SubscribeFormSchema), resolver: zodResolver(SubscribeFormSchema),
defaultValues: { defaultValues: {
@@ -58,7 +68,7 @@ export default function Home() {
} }
} }
function render() { const renderContent = () => {
if (error) { if (error) {
return ErrorMessage(); return ErrorMessage();
} }
@@ -105,14 +115,17 @@ export default function Home() {
</p> </p>
</div> </div>
); );
} };
return ( return (
<CustomCard <>
className='max-90vw w-96' <Schema schema={schema} />
title='Interested in keeping up with the latest from the tech world? 👩‍💻' <CustomCard
description='Subscribe to our newsletter! The top stories from Hackernews for you. Once a day. Every day.' className='max-90vw w-96'
content={render()} title='Interested in keeping up with the latest from the tech world? 👩‍💻'
/> description='Subscribe to our newsletter! The top stories from Hackernews for you. Once a day. Every day.'
content={renderContent()}
/>
</>
); );
} }

View File

@@ -1,9 +1,18 @@
'use client'; 'use client';
import CustomCard from '@components/CustomCard'; import CustomCard from '@components/CustomCard';
import Schema from '@components/SchemaOrg';
import Link from 'next/link'; import Link from 'next/link';
export default function Privacy() { export default function Privacy() {
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'HackerNews Newsletter',
title: 'Privacy Policy',
url: `${process.env.HOME_URL}/privacy`
};
const body = ( const body = (
<div className='my-2 max-h-[60vh] overflow-auto'> <div className='my-2 max-h-[60vh] overflow-auto'>
<p> <p>
@@ -439,11 +448,14 @@ export default function Privacy() {
); );
return ( return (
<CustomCard <>
className='max-90vh max-90vw' <Schema schema={schema} />
title='Privacy Policy' <CustomCard
description='Last updated: December 03, 2023' className='max-90vh max-90vw'
content={body} title='Privacy Policy'
/> description='Last updated: December 03, 2023'
content={body}
/>
</>
); );
} }

View File

@@ -1,4 +1,5 @@
'use client'; 'use client';
import { Button } from '@components/Button'; import { Button } from '@components/Button';
import { CardDescription } from '@components/Card'; import { CardDescription } from '@components/Card';
import CustomCard from '@components/CustomCard'; import CustomCard from '@components/CustomCard';
@@ -6,6 +7,7 @@ import ErrorMessage from '@components/ErrorMessage';
import { FormControl } from '@components/form/FormControl'; import { FormControl } from '@components/form/FormControl';
import { FormMessage } from '@components/form/FormMessage'; import { FormMessage } from '@components/form/FormMessage';
import { Input } from '@components/Input'; import { Input } from '@components/Input';
import Schema from '@components/SchemaOrg';
import { FormField } from '@contexts/FormField/FormFieldProvider'; import { FormField } from '@contexts/FormField/FormFieldProvider';
import { FormItem } from '@contexts/FormItem/FormItemProvider'; import { FormItem } from '@contexts/FormItem/FormItemProvider';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
@@ -23,6 +25,14 @@ export default function Unsubscribe() {
const [error, setError] = useState(false); const [error, setError] = useState(false);
const ref = useRef<HTMLInputElement | null>(null); const ref = useRef<HTMLInputElement | null>(null);
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'HackerNews Newsletter',
title: 'Unsubscribe',
url: `${process.env.HOME_URL}/unsubscribe`
};
const form = useForm<UnsubscribeFormType>({ const form = useForm<UnsubscribeFormType>({
resolver: zodResolver(UnsubscribeFormSchema), resolver: zodResolver(UnsubscribeFormSchema),
defaultValues: { defaultValues: {
@@ -65,7 +75,7 @@ export default function Unsubscribe() {
} }
} }
function render() { const renderContent = () => {
if (error) { if (error) {
return ErrorMessage(); return ErrorMessage();
} }
@@ -108,14 +118,17 @@ export default function Unsubscribe() {
</FormProvider> </FormProvider>
</div> </div>
); );
} };
return ( return (
<CustomCard <>
className='max-90vw w-96' <Schema schema={schema} />
title='Unsubscribe' <CustomCard
description='You sure you want to leave? :(' className='max-90vw w-96'
content={render()} title='Unsubscribe'
/> description='You sure you want to leave? :('
content={renderContent()}
/>
</>
); );
} }

13
components/SchemaOrg.tsx Normal file
View File

@@ -0,0 +1,13 @@
import Head from 'next/head';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const SchemaOrg = ({ schema }: Record<string, any>) => (
<Head>
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
</Head>
);
export default SchemaOrg;