Improve SEO metadata and add sitemap
This commit is contained in:
parent
357194edad
commit
7e3b72d8f3
12 changed files with 168 additions and 9 deletions
|
|
@ -3,24 +3,27 @@
|
|||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Highland Group RDA | Enriching Lives Through Horses</title>
|
||||
<title>Highland Group RDA - Home</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Highland Group RDA brings meaningful, positive change to people with disabilities through equine activities in the Highlands."
|
||||
content="Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities."
|
||||
/>
|
||||
<link rel="canonical" href="https://rda-2026.calumamuir.workers.dev" />
|
||||
<meta property="og:title" content="Highland Group RDA" />
|
||||
<link rel="canonical" href="https://highlandgrouprda.org.uk" />
|
||||
<meta property="og:title" content="Highland Group RDA - Home" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Enriching lives through horses in the Highlands since 1975."
|
||||
content="Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities."
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://rda-2026.calumamuir.workers.dev"
|
||||
/>
|
||||
<meta property="og:url" content="https://highlandgrouprda.org.uk" />
|
||||
<meta property="og:image" content="/Samantha-and-Connolly.jpg" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Highland Group RDA - Home" />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities."
|
||||
/>
|
||||
<meta name="twitter:image" content="/Samantha-and-Connolly.jpg" />
|
||||
<meta name="theme-color" content="#e2e2e2" />
|
||||
<link rel="preload" as="image" href="/Samantha-and-Connolly.jpg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://highlandgrouprda.org.uk/sitemap.xml
|
||||
|
|
|
|||
36
client/public/sitemap.xml
Normal file
36
client/public/sitemap.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/about</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/news</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/news/volunteers-summer-2024</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/news/summer-awards-2024</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/news/race-night</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/news/important-news</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/support</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/contact</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/privacy</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://highlandgrouprda.org.uk/facebook</loc>
|
||||
</url>
|
||||
</urlset>
|
||||
66
client/src/lib/seo.ts
Normal file
66
client/src/lib/seo.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { useEffect } from "react";
|
||||
|
||||
const SITE_NAME = "Highland Group RDA";
|
||||
const BASE_URL = "https://highlandgrouprda.org.uk";
|
||||
const DEFAULT_DESCRIPTION =
|
||||
"Highland Group RDA provides horse riding for people with disabilities in the Highlands, offering safe, fun, and therapeutic equestrian activities.";
|
||||
const DEFAULT_IMAGE = "/Samantha-and-Connolly.jpg";
|
||||
|
||||
type PageMeta = {
|
||||
title: string;
|
||||
description?: string;
|
||||
path?: string;
|
||||
image?: string;
|
||||
};
|
||||
|
||||
const setMeta = (attr: "name" | "property", key: string, value: string) => {
|
||||
let tag = document.head.querySelector<HTMLMetaElement>(
|
||||
`meta[${attr}="${key}"]`,
|
||||
);
|
||||
if (!tag) {
|
||||
tag = document.createElement("meta");
|
||||
tag.setAttribute(attr, key);
|
||||
document.head.appendChild(tag);
|
||||
}
|
||||
tag.setAttribute("content", value);
|
||||
};
|
||||
|
||||
const setCanonical = (href: string) => {
|
||||
let link = document.head.querySelector<HTMLLinkElement>(
|
||||
'link[rel="canonical"]',
|
||||
);
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.setAttribute("rel", "canonical");
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
link.setAttribute("href", href);
|
||||
};
|
||||
|
||||
export const usePageMeta = ({
|
||||
title,
|
||||
description = DEFAULT_DESCRIPTION,
|
||||
path = "/",
|
||||
image = DEFAULT_IMAGE,
|
||||
}: PageMeta): void => {
|
||||
useEffect(() => {
|
||||
const pageTitle = `${SITE_NAME} - ${title}`;
|
||||
const url = `${BASE_URL}${path === "/" ? "" : path}`;
|
||||
const imageUrl = image.startsWith("http")
|
||||
? image
|
||||
: `${BASE_URL}${image}`;
|
||||
|
||||
document.title = pageTitle;
|
||||
setMeta("name", "description", description);
|
||||
setMeta("property", "og:title", pageTitle);
|
||||
setMeta("property", "og:description", description);
|
||||
setMeta("property", "og:type", "website");
|
||||
setMeta("property", "og:url", url);
|
||||
setMeta("property", "og:image", imageUrl);
|
||||
setMeta("name", "twitter:card", "summary_large_image");
|
||||
setMeta("name", "twitter:title", pageTitle);
|
||||
setMeta("name", "twitter:description", description);
|
||||
setMeta("name", "twitter:image", imageUrl);
|
||||
setCanonical(url);
|
||||
}, [title, description, path, image]);
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -11,6 +12,12 @@ const navigationItems = [
|
|||
];
|
||||
|
||||
export const About = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "About",
|
||||
path: "/about",
|
||||
description:
|
||||
"Learn about Highland Group RDA, our mission, and how we support riders across the Highlands.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -11,6 +12,12 @@ const navigationItems = [
|
|||
];
|
||||
|
||||
export const Contact = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "Contact",
|
||||
path: "/contact",
|
||||
description:
|
||||
"Contact Highland Group RDA for sessions, volunteering, and support.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -35,6 +36,7 @@ const cardData = [
|
|||
];
|
||||
|
||||
export const Desktop = (): JSX.Element => {
|
||||
usePageMeta({ title: "Home", path: "/" });
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -17,6 +18,12 @@ const facebookEmbedUrl =
|
|||
"https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2Fprofile.php%3Fid%3D100064729054822&tabs=timeline&width=500&height=900&small_header=false&adapt_container_width=true&hide_cover=false&show_facepile=true";
|
||||
|
||||
export const Facebook = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "Facebook",
|
||||
path: "/facebook",
|
||||
description:
|
||||
"Follow Highland Group RDA on Facebook for the latest updates and events.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { formatNewsDate, newsArticles } from "@/lib/news";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -12,6 +13,12 @@ const navigationItems = [
|
|||
];
|
||||
|
||||
export const News = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "News",
|
||||
path: "/news",
|
||||
description:
|
||||
"News, events, and updates from Highland Group RDA and our community.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useRoute } from "wouter";
|
|||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { formatNewsDate, getNewsArticle } from "@/lib/news";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
import NotFound from "@/pages/not-found";
|
||||
|
||||
const navigationItems = [
|
||||
|
|
@ -21,6 +22,13 @@ export const NewsArticle = (): JSX.Element => {
|
|||
return <NotFound />;
|
||||
}
|
||||
|
||||
usePageMeta({
|
||||
title: article.title,
|
||||
path: `/news/${article.slug}`,
|
||||
description: article.summary,
|
||||
image: article.image,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -11,6 +12,12 @@ const navigationItems = [
|
|||
];
|
||||
|
||||
export const Privacy = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "Privacy Policy",
|
||||
path: "/privacy",
|
||||
description:
|
||||
"Privacy policy for Highland Group RDA, including our use of Cloudflare Web Analytics.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<SiteHeader
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { usePageMeta } from "@/lib/seo";
|
||||
|
||||
const navigationItems = [
|
||||
{ label: "Home", href: "/" },
|
||||
|
|
@ -11,6 +12,12 @@ const navigationItems = [
|
|||
];
|
||||
|
||||
export const SupportUs = (): JSX.Element => {
|
||||
usePageMeta({
|
||||
title: "Support Us",
|
||||
path: "/support",
|
||||
description:
|
||||
"Support Highland Group RDA through donations, volunteering, and fundraising.",
|
||||
});
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen items-center bg-[#e2e2e2]">
|
||||
<main className="w-full">
|
||||
|
|
|
|||
Loading…
Reference in a new issue