feat: add schema.org metadata
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { CardDescription } from '@components/Card';
|
||||
import CustomCard from '@components/CustomCard';
|
||||
import Schema from '@components/SchemaOrg';
|
||||
import { ResponseType } from '@utils/validationSchemas';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import { Suspense, useEffect, useState } from 'react';
|
||||
@@ -54,7 +56,7 @@ function ConfirmationPage() {
|
||||
fetchData();
|
||||
}, [code, router]);
|
||||
|
||||
function render() {
|
||||
const renderContent = () => {
|
||||
if (!loading) {
|
||||
return (
|
||||
<CardDescription className='text-center'>{message}</CardDescription>
|
||||
@@ -62,22 +64,33 @@ function ConfirmationPage() {
|
||||
}
|
||||
|
||||
return 'Just a second...';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomCard
|
||||
className='max-90vw w-96'
|
||||
title={loading ? 'Verifying' : 'Confirmed!'}
|
||||
content={render()}
|
||||
content={renderContent()}
|
||||
footer={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<Suspense fallback={<>Loading...</>}>
|
||||
<ConfirmationPage />
|
||||
</Suspense>
|
||||
<>
|
||||
<Schema schema={schema} />
|
||||
<Suspense fallback={<>Loading...</>}>
|
||||
<ConfirmationPage />
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
29
app/page.tsx
29
app/page.tsx
@@ -1,4 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@components/Button';
|
||||
import { CardDescription } from '@components/Card';
|
||||
import CustomCard from '@components/CustomCard';
|
||||
@@ -6,6 +7,7 @@ import ErrorMessage from '@components/ErrorMessage';
|
||||
import { FormControl } from '@components/form/FormControl';
|
||||
import { FormMessage } from '@components/form/FormMessage';
|
||||
import { Input } from '@components/Input';
|
||||
import Schema from '@components/SchemaOrg';
|
||||
import { FormField } from '@contexts/FormField/FormFieldProvider';
|
||||
import { FormItem } from '@contexts/FormItem/FormItemProvider';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
@@ -22,6 +24,14 @@ export default function Home() {
|
||||
const [message, setMessage] = useState('');
|
||||
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>({
|
||||
resolver: zodResolver(SubscribeFormSchema),
|
||||
defaultValues: {
|
||||
@@ -58,7 +68,7 @@ export default function Home() {
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
const renderContent = () => {
|
||||
if (error) {
|
||||
return ErrorMessage();
|
||||
}
|
||||
@@ -105,14 +115,17 @@ export default function Home() {
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomCard
|
||||
className='max-90vw w-96'
|
||||
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={render()}
|
||||
/>
|
||||
<>
|
||||
<Schema schema={schema} />
|
||||
<CustomCard
|
||||
className='max-90vw w-96'
|
||||
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()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
'use client';
|
||||
|
||||
import CustomCard from '@components/CustomCard';
|
||||
import Schema from '@components/SchemaOrg';
|
||||
import Link from 'next/link';
|
||||
|
||||
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 = (
|
||||
<div className='my-2 max-h-[60vh] overflow-auto'>
|
||||
<p>
|
||||
@@ -439,11 +448,14 @@ export default function Privacy() {
|
||||
);
|
||||
|
||||
return (
|
||||
<CustomCard
|
||||
className='max-90vh max-90vw'
|
||||
title='Privacy Policy'
|
||||
description='Last updated: December 03, 2023'
|
||||
content={body}
|
||||
/>
|
||||
<>
|
||||
<Schema schema={schema} />
|
||||
<CustomCard
|
||||
className='max-90vh max-90vw'
|
||||
title='Privacy Policy'
|
||||
description='Last updated: December 03, 2023'
|
||||
content={body}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@components/Button';
|
||||
import { CardDescription } from '@components/Card';
|
||||
import CustomCard from '@components/CustomCard';
|
||||
@@ -6,6 +7,7 @@ import ErrorMessage from '@components/ErrorMessage';
|
||||
import { FormControl } from '@components/form/FormControl';
|
||||
import { FormMessage } from '@components/form/FormMessage';
|
||||
import { Input } from '@components/Input';
|
||||
import Schema from '@components/SchemaOrg';
|
||||
import { FormField } from '@contexts/FormField/FormFieldProvider';
|
||||
import { FormItem } from '@contexts/FormItem/FormItemProvider';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
@@ -23,6 +25,14 @@ export default function Unsubscribe() {
|
||||
const [error, setError] = useState(false);
|
||||
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>({
|
||||
resolver: zodResolver(UnsubscribeFormSchema),
|
||||
defaultValues: {
|
||||
@@ -65,7 +75,7 @@ export default function Unsubscribe() {
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
const renderContent = () => {
|
||||
if (error) {
|
||||
return ErrorMessage();
|
||||
}
|
||||
@@ -108,14 +118,17 @@ export default function Unsubscribe() {
|
||||
</FormProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomCard
|
||||
className='max-90vw w-96'
|
||||
title='Unsubscribe'
|
||||
description='You sure you want to leave? :('
|
||||
content={render()}
|
||||
/>
|
||||
<>
|
||||
<Schema schema={schema} />
|
||||
<CustomCard
|
||||
className='max-90vw w-96'
|
||||
title='Unsubscribe'
|
||||
description='You sure you want to leave? :('
|
||||
content={renderContent()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
13
components/SchemaOrg.tsx
Normal file
13
components/SchemaOrg.tsx
Normal 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;
|
||||
Reference in New Issue
Block a user