Skip to content

Commit

Permalink
feat: configure SEO for contact page
Browse files Browse the repository at this point in the history
  • Loading branch information
AshGw committed May 22, 2024
1 parent 9de983a commit c5b6b43
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 100 deletions.
9 changes: 4 additions & 5 deletions src/app/(pages)/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ import { pub } from '@/lib/env';
import { getSiteName } from '@/lib/funcs/site-name';
import type { Metadata } from 'next';

const SERVICES_URL = new URL(pub.SITE_URL_PROD + '/about');
const PAGE_URL = new URL(pub.SITE_URL_PROD + '/about');
const creator = 'Ashref Gwader';
const title = 'About';
const description = "I'moftware developer and technical educator";
const url = SERVICES_URL;
const description = "I'm a software developer and technical educator";
const kw: string[] = [creator, 'ashgw', 'about'];

const postImageWidth = 1200; // in pixels
const postImageHeight = 630;
const postImageUrl = `https://via.placeholder.com/${postImageWidth}x${postImageHeight}.png/000000/ffffff/?text=${title}`;

export const metadata: Metadata = {
metadataBase: SERVICES_URL,
metadataBase: PAGE_URL,
title: {
default: title,
template: '%s | Ashgw',
Expand All @@ -30,7 +29,7 @@ export const metadata: Metadata = {
title,
description,
type: 'article',
url,
url: PAGE_URL,
images: [
{
url: postImageUrl,
Expand Down
99 changes: 99 additions & 0 deletions src/app/(pages)/contact/_contact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
'use client';

import Footer from '@/app/components/footer/footer';
import { TextContent as C } from '@/app/components/reusables/content';
import { Heading1 as H1 } from '@/app/components/reusables/headers';
import { Button } from '@/app/components/ui/button';
import { EMAIL, GPG_PUBLIC_KEY_INTERNAL_URL } from '@/lib/constants';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { useCopyToClipboard } from 'react-use';
import { Toaster, toast } from 'sonner';

export default function Main() {
const [, copyToClipboard] = useCopyToClipboard();

const successToast = () => {
toast.message('Key ID: 79821E0224D34EC4969FF6A8E5168EE090AE80D0', {
description: 'The public key block has been copied to your clipboard',
});
};

const failToast = (message?: string) => {
toast.message('Oops! Looks like something went wrong!', {
description: message,
});
};

async function copyGPG() {
const res = await fetch(GPG_PUBLIC_KEY_INTERNAL_URL, {
method: 'GET',
});
if (!res.ok) {
const failureMessage = await res.text();
failToast(failureMessage);
}
const key = await res.text();
copyToClipboard(key);
successToast();
}
return (
<div className="flex flex-col">
<main className="flex-1">
<section className="w-full mt-20 py-12 md:mt-0 md:py-24 lg:py-32 xl:py-48">
<div className="container px-4 md:px-6">
<div className="space-y-6 text-center">
<div className="space-y-2">
<H1>
<span className="">Get in touch</span>
</H1>
<div className="mx-auto max-w-[600px]">
<C>
Feel free to reach out through email. I will get back to you
as soon as possible. If you prefer to communicate securely,
use my <span> </span>
<button
onClick={async () => {
await copyGPG();
}}
>
<strong className="text-white glows underline">
GPG
</strong>
</button>
<span> </span> key to encrypt messages before you
</C>
</div>
</div>
<div className="mx-auto max-w-sm space-y-2">
<motion.div
className="space-y-4 "
initial={{
opacity: 0,
scale: 0.8,
}}
animate={{
opacity: 1,
scale: 1,
}}
transition={{
duration: 0.4,
delay: 1,
}}
>
<Link href={`mailto:${EMAIL}`}>
<Button className="glowsup" variant="navbar">
email me
</Button>
</Link>
</motion.div>
</div>
</div>
</div>
</section>
</main>
<Footer />
<Toaster />
</div>
);
}
154 changes: 59 additions & 95 deletions src/app/(pages)/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -1,99 +1,63 @@
'use client';
import Contact from '@/app/(pages)/contact/_contact';
import { pub } from '@/lib/env';
import { getSiteName } from '@/lib/funcs/site-name';
import type { Metadata } from 'next';

import Footer from '@/app/components/footer/footer';
import { TextContent as C } from '@/app/components/reusables/content';
import { Heading1 as H1 } from '@/app/components/reusables/headers';
import { Button } from '@/app/components/ui/button';
import { EMAIL, GPG_PUBLIC_KEY_INTERNAL_URL } from '@/lib/constants';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { useCopyToClipboard } from 'react-use';
import { Toaster, toast } from 'sonner';
const PAGE_URL = new URL(pub.SITE_URL_PROD + '/contact');
const creator = 'Ashref Gwader';
const title = 'About';
const description = 'Contact me through email';
const kw: string[] = [creator, 'ashgw', 'contact'];

export default function Main() {
const [, copyToClipboard] = useCopyToClipboard();
const postImageWidth = 1200; // in pixels
const postImageHeight = 630;
const postImageUrl = `https://via.placeholder.com/${postImageWidth}x${postImageHeight}.png/000000/ffffff/?text=${title}`;

const successToast = () => {
toast.message('Key ID: 79821E0224D34EC4969FF6A8E5168EE090AE80D0', {
description: 'The public key block has been copied to your clipboard',
});
};

const failToast = (message?: string) => {
toast.message('Oops! Looks like something went wrong!', {
description: message,
});
};

async function copyGPG() {
const res = await fetch(GPG_PUBLIC_KEY_INTERNAL_URL, {
method: 'GET',
});
if (!res.ok) {
const failureMessage = await res.text();
failToast(failureMessage);
}
const key = await res.text();
copyToClipboard(key);
successToast();
}
return (
<div className="flex flex-col">
<main className="flex-1">
<section className="w-full mt-20 py-12 md:mt-0 md:py-24 lg:py-32 xl:py-48">
<div className="container px-4 md:px-6">
<div className="space-y-6 text-center">
<div className="space-y-2">
<H1>
<span className="">Get in touch</span>
</H1>
<div className="mx-auto max-w-[600px]">
<C>
Feel free to reach out through email. I will get back to you
as soon as possible. If you prefer to communicate securely,
use my <span> </span>
<button
onClick={async () => {
await copyGPG();
}}
>
<strong className="text-white glows underline">
GPG
</strong>
</button>
<span> </span> key to encrypt messages before you
</C>
</div>
</div>
<div className="mx-auto max-w-sm space-y-2">
<motion.div
className="space-y-4 "
initial={{
opacity: 0,
scale: 0.8,
}}
animate={{
opacity: 1,
scale: 1,
}}
transition={{
duration: 0.4,
delay: 1,
}}
>
<Link href={`mailto:${EMAIL}`}>
<Button className="glowsup" variant="navbar">
email me
</Button>
</Link>
</motion.div>
</div>
</div>
</div>
</section>
</main>
<Footer />
<Toaster />
</div>
);
export const metadata: Metadata = {
metadataBase: PAGE_URL,
title: {
default: title,
template: '%s | Ashgw',
},
creator: creator,
keywords: kw,
description: description,
openGraph: {
siteName: getSiteName(pub.SITE_URL_PROD) || pub.SITE_URL_PROD,
locale: 'en_US',
publishedTime: '2023-12-01T09:15:00-0401',
title,
description,
type: 'article',
url: PAGE_URL,
images: [
{
url: postImageUrl,
width: postImageWidth,
height: postImageHeight,
alt: title,
},
],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
twitter: {
card: 'summary_large_image',
title,
description,
images: [postImageUrl],
},
category: 'tech',
};
export default function Page() {
return <Contact />;
}
4 changes: 4 additions & 0 deletions src/app/components/protos/hero-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ import { Button } from '../ui/button';

/* eslint-disable */

/* eslint-disable */

/* eslint-disable */

function TypingAnimation() {
const el = useRef(null);

Expand Down
10 changes: 10 additions & 0 deletions src/app/components/reusables/code/code-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,16 @@ import CopyButton from './copy-code';
/* eslint-disable */
// @ts-nocheck

// react-syntax-highlighter has no types

/* eslint-disable */
// @ts-nocheck

// react-syntax-highlighter has no types

/* eslint-disable */
// @ts-nocheck

// react-syntax-highlighter has no types
/* eslint-disable */
// @ts-nocheck
Expand Down

0 comments on commit c5b6b43

Please sign in to comment.