Add shared SEO layout and page metadata

This commit is contained in:
Calum Muir 2025-12-29 12:51:36 +00:00
parent dbb51210ab
commit d50b2971e9
13 changed files with 198 additions and 143 deletions

BIN
public/og/default.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

10
src/config/site.ts Normal file
View file

@ -0,0 +1,10 @@
export const SITE_NAME = "Highland Group RDA";
const siteUrlFromEnv =
import.meta.env.SITE ?? "https://highlandgrouprda.org.uk";
export const SITE_URL = siteUrlFromEnv;
export const DEFAULT_OG_IMAGE = "/og/default.jpg";
export const TWITTER_SITE = "@HighlandGroupRDA";
export const TWITTER_CARD = "summary_large_image";
export const OG_TYPE = "website";

View file

@ -1,91 +1,18 @@
---
import "../styles/global.css";
import BaseLayout from "./BaseLayout.astro";
const {
title = "Home",
description = "Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities.",
keywords = "Highland Group RDA, horse riding for disabilities, therapeutic riding Highlands, RDA Scotland, equestrian therapy, disability riding lessons",
path = "/",
image = "/Samantha-and-Connolly-1280.webp",
} = Astro.props;
const SITE_NAME = "Highland Group RDA";
const BASE_URL = "https://highlandgrouprda.org.uk";
const pageTitle = `${SITE_NAME} - ${title}`;
const canonical = path === "/" ? BASE_URL : `${BASE_URL}${path}`;
const imageUrl = image.startsWith("http") ? image : `${BASE_URL}${image}`;
const { title, description, keywords, path, image } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{pageTitle}</title>
<meta name="description" content={description} />
<meta name="keywords" content={keywords} />
<link rel="canonical" href={canonical} />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:url" content={canonical} />
<meta property="og:image" content={imageUrl} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={imageUrl} />
<meta name="theme-color" content="#e2e2e2" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href="/favicon-96x96.png"
/>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@600;700;800&family=Merriweather:wght@700&display=swap"
rel="stylesheet"
/>
<BaseLayout
title={title}
description={description}
keywords={keywords}
canonicalPath={path}
ogImage={image}
>
<Fragment slot="head">
<slot name="head" />
<script
src="https://cdn.userway.org/widget.js"
data-account="ZdcVJAc6ri"></script>
</head>
<body>
<div
class="snow-banner"
role="region"
aria-label="Holiday announcement"
>
<div class="snow-banner__snow" aria-hidden="true">
<span class="snowflake snowflake-1"></span>
<span class="snowflake snowflake-2"></span>
<span class="snowflake snowflake-3"></span>
<span class="snowflake snowflake-4"></span>
<span class="snowflake snowflake-5"></span>
<span class="snowflake snowflake-6"></span>
<span class="snowflake snowflake-7"></span>
<span class="snowflake snowflake-8"></span>
</div>
<a
class="snow-banner__link"
href="https://www.amazon.co.uk/hz/wishlist/ls/2B4R5YZQ8U4B2?ref_=wl_share"
target="_blank"
rel="noreferrer"
>
The ponies have had a chat and put together an Amazon Wish-List
for Christmas! Click here
</a>
</div>
</Fragment>
<slot />
</body>
</html>
</BaseLayout>

View file

@ -0,0 +1,104 @@
---
import "../styles/global.css";
import {
DEFAULT_OG_IMAGE,
OG_TYPE,
SITE_NAME,
SITE_URL,
TWITTER_CARD,
TWITTER_SITE,
} from "../config/site";
const { title = "", description, keywords, canonicalPath, ogImage } =
Astro.props;
const pageTitle =
title && title !== SITE_NAME ? `${title} | ${SITE_NAME}` : SITE_NAME;
const canonicalUrl = new URL(
canonicalPath ?? Astro.url.pathname,
SITE_URL
).toString();
const ogImagePath = ogImage ?? DEFAULT_OG_IMAGE;
const ogImageUrl = ogImagePath
? new URL(ogImagePath, SITE_URL).toString()
: "";
const hasOgImage = Boolean(ogImagePath);
const twitterSite = TWITTER_SITE?.trim();
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{pageTitle}</title>
<meta name="description" content={description} />
<meta name="keywords" content={keywords} />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:site_name" content={SITE_NAME} />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={description} />
<meta property="og:type" content={OG_TYPE} />
<meta property="og:url" content={canonicalUrl} />
{hasOgImage && <meta property="og:image" content={ogImageUrl} />}
<meta name="twitter:card" content={TWITTER_CARD} />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={description} />
{hasOgImage && <meta name="twitter:image" content={ogImageUrl} />}
{twitterSite && <meta name="twitter:site" content={twitterSite} />}
<meta name="theme-color" content="#e2e2e2" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href="/favicon-96x96.png"
/>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@600;700;800&family=Merriweather:wght@700&display=swap"
rel="stylesheet"
/>
<slot name="head" />
<script
src="https://cdn.userway.org/widget.js"
data-account="ZdcVJAc6ri"></script>
</head>
<body>
<div
class="snow-banner"
role="region"
aria-label="Holiday announcement"
>
<div class="snow-banner__snow" aria-hidden="true">
<span class="snowflake snowflake-1"></span>
<span class="snowflake snowflake-2"></span>
<span class="snowflake snowflake-3"></span>
<span class="snowflake snowflake-4"></span>
<span class="snowflake snowflake-5"></span>
<span class="snowflake snowflake-6"></span>
<span class="snowflake snowflake-7"></span>
<span class="snowflake snowflake-8"></span>
</div>
<a
class="snow-banner__link"
href="https://www.amazon.co.uk/hz/wishlist/ls/2B4R5YZQ8U4B2?ref_=wl_share"
target="_blank"
rel="noreferrer"
>
The ponies have had a chat and put together an Amazon Wish-List
for Christmas! Click here
</a>
</div>
<slot />
</body>
</html>

View file

@ -2,29 +2,43 @@
import Base from "../layouts/Base.astro";
---
<Base title="Page not found" path="/404">
<div class="min-h-screen w-full flex items-center justify-center bg-[#e2e2e2] px-4">
<div class="w-full max-w-md rounded-lg border border-black/10 bg-white/90 px-6 py-6 shadow-sm">
<Base
title="Page not found"
path="/404"
description="The page you are looking for could not be found on the Highland Group RDA website."
keywords="Highland Group RDA, 404, page not found, missing page"
>
<div
class="min-h-screen w-full flex items-center justify-center bg-[#e2e2e2] px-4"
>
<div
class="w-full max-w-md rounded-lg border border-black/10 bg-white/90 px-6 py-6 shadow-sm"
>
<div class="flex items-center gap-3">
<span class="inline-flex h-10 w-10 items-center justify-center rounded-full bg-red-100 text-red-500">
<span
class="inline-flex h-10 w-10 items-center justify-center rounded-full bg-red-100 text-red-500"
>
<svg viewBox="0 0 24 24" class="h-6 w-6" aria-hidden="true">
<path
fill="currentColor"
d="M11 7h2v6h-2zm0 8h2v2h-2z"
/>
<path fill="currentColor" d="M11 7h2v6h-2zm0 8h2v2h-2z"
></path>
<path
fill="currentColor"
d="M12 2 1 21h22z"
opacity="0.15"
/>
opacity="0.15"></path>
</svg>
</span>
<h1 class="text-2xl font-bold text-gray-900">404 Page Not Found</h1>
<h1 class="text-2xl font-bold text-gray-900">
404 Page Not Found
</h1>
</div>
<p class="mt-4 text-sm text-gray-600">
The page you are looking for does not exist. Try heading back to the homepage.
The page you are looking for does not exist. Try heading back to
the homepage.
</p>
<a class="mt-6 inline-flex text-sm font-semibold text-black underline" href="/">Return home</a>
<a
class="mt-6 inline-flex text-sm font-semibold text-black underline"
href="/">Return home</a
>
</div>
</div>
</Base>

View file

@ -1,20 +1,20 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "About",
path: "/about",
description:
"Highland Group RDA is a volunteer-led charity offering therapeutic horse riding in the Highlands. Learn about our mission, history, and community impact.",
keywords:
"Highland Group RDA, about Highland RDA, RDA charity, volunteer-led charity Scotland, therapeutic riding, equestrian therapy Highlands",
canonicalPath: "/about",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section class="w-full max-w-[1200px] mx-auto px-0 sm:px-8 mt-0">
@ -380,4 +380,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,20 +1,20 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "Accessibility",
path: "/accessibility",
description:
"Read Highland Group RDA's Accessibility Statement and learn how we make our website inclusive and accessible for all users.",
keywords:
"Highland Group RDA accessibility, accessible charity website, web accessibility statement, inclusive design Scotland, RDA accessibility",
canonicalPath: "/accessibility",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section
@ -171,4 +171,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,22 +1,22 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "Contact",
path: "/contact",
description:
"Contact Highland Group RDA for bookings, volunteering, or enquiries. We're here to help you connect with our team and activities in the Highlands.",
keywords:
"Highland Group RDA contact, RDA enquiries, book RDA session, volunteer at RDA, RDA Highlands contact details, disability riding information",
canonicalPath: "/contact",
};
const turnstileSiteKey = import.meta.env.PUBLIC_TURNSTILE_SITE_KEY ?? "";
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
{
turnstileSiteKey && (
<Fragment slot="head">
@ -223,4 +223,4 @@ const turnstileSiteKey = import.meta.env.PUBLIC_TURNSTILE_SITE_KEY ?? "";
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,5 +1,5 @@
---
import Base from "../../layouts/Base.astro";
import BaseLayout from "../../layouts/BaseLayout.astro";
import SiteHeader from "../../components/SiteHeader.astro";
import SiteFooter from "../../components/SiteFooter.astro";
import { navigationItems } from "../../lib/navigation";
@ -7,15 +7,15 @@ import { newsArticles, formatNewsDate } from "../../lib/news";
const pageSeo = {
title: "News",
path: "/events",
description:
"Stay updated with Highland Group RDA news, events, and stories. Discover how our riders, volunteers, and community are making a difference every day.",
keywords:
"Highland RDA news, RDA events, disability riding stories, RDA updates, equestrian therapy news, Highlands charity events",
canonicalPath: "/events",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section class="w-full max-w-[1200px] mx-auto px-0 sm:px-8 mt-0">
@ -113,4 +113,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,5 +1,5 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
@ -11,15 +11,15 @@ const facebookEmbedUrl =
const pageSeo = {
title: "Facebook",
path: "/facebook",
description:
"Follow Highland Group RDA on Facebook to see the latest updates, photos, events, and stories from our riders, volunteers, and community.",
keywords:
"Highland Group RDA Facebook, RDA social media, Highland RDA updates, RDA events Facebook, therapeutic riding community",
canonicalPath: "/facebook",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section class="w-full max-w-[1200px] mx-auto px-0 sm:px-8 mt-0">
@ -101,4 +101,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,16 +1,16 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "Home",
path: "/",
title: "Highland Group RDA",
description:
"Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities.",
keywords:
"Highland Group RDA, horse riding for disabilities, therapeutic riding Highlands, RDA Scotland, equestrian therapy, disability riding lessons",
canonicalPath: "/",
};
const cardData = [
@ -35,7 +35,7 @@ const cardData = [
];
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<Fragment slot="head">
<link
rel="preload"
@ -222,4 +222,4 @@ const cardData = [
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,20 +1,20 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "Privacy Policy",
path: "/privacy",
description:
"Read Highland Group RDA's Privacy Policy to learn how we collect, use, and protect your personal information in line with data protection laws.",
keywords:
"Highland Group RDA privacy policy, data protection RDA, GDPR compliance Scotland, RDA data use, protect personal information",
canonicalPath: "/privacy",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section
@ -351,4 +351,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>

View file

@ -1,20 +1,20 @@
---
import Base from "../layouts/Base.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import SiteHeader from "../components/SiteHeader.astro";
import SiteFooter from "../components/SiteFooter.astro";
import { navigationItems } from "../lib/navigation";
const pageSeo = {
title: "Support Us",
path: "/support-us",
description:
"Support Highland Group RDA through donations, volunteering, or fundraising. Help us provide free, life-changing horse riding sessions in the Highlands.",
keywords:
"Support Highland RDA, donate to RDA, RDA fundraising, volunteer with RDA, charity donations Scotland, equestrian therapy support",
canonicalPath: "/support-us",
};
---
<Base {...pageSeo}>
<BaseLayout {...pageSeo}>
<div class="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
<main class="w-full">
<section class="w-full max-w-[1200px] mx-auto px-0 sm:px-8 mt-0">
@ -356,4 +356,4 @@ const pageSeo = {
<SiteFooter fullBleedOnMobile />
</main>
</div>
</Base>
</BaseLayout>