feat: add SEO component and integrate it across multiple pages with localised metadata
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useTranslation } from "react-i18next"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
/**
|
||||
* About page component that displays information about the DevLab application.
|
||||
@@ -8,6 +9,11 @@ export default function About() {
|
||||
|
||||
return (
|
||||
<div className="space-y-8 max-w-6xl mx-auto">
|
||||
<Seo
|
||||
title={t("seo.about.title")}
|
||||
description={t("seo.about.description")}
|
||||
path="/about"
|
||||
/>
|
||||
{/* Page Header */}
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-bold text-gray-900 sm:text-4xl">{t("about.title")}</h1>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
/**
|
||||
* BMI Calculator page component that displays the BMI calculator tool.
|
||||
@@ -72,6 +73,11 @@ export default function BmiCalculator() {
|
||||
|
||||
return (
|
||||
<div className="h-full flex gap-4 overflow-hidden">
|
||||
<Seo
|
||||
title={t("seo.bmi.title")}
|
||||
description={t("seo.bmi.description")}
|
||||
path="/bmi-calculator"
|
||||
/>
|
||||
{/* Left panel - 30% */}
|
||||
<div className="w-[30%] flex flex-col gap-4 min-h-0">
|
||||
{/* Input Form - fills remaining height */}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
/**
|
||||
* Contact page component that encourages manual GitHub Issue submission.
|
||||
@@ -38,6 +39,11 @@ ${message}
|
||||
|
||||
return (
|
||||
<div className="max-w-5xl mx-auto py-12 px-4 sm:px-6">
|
||||
<Seo
|
||||
title={t("seo.contact.title")}
|
||||
description={t("seo.contact.description")}
|
||||
path="/contact"
|
||||
/>
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-3xl font-bold text-gray-900 sm:text-4xl">{t("contact.title")}</h1>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Link } from "react-router-dom"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
/**
|
||||
* Home page component that displays the main landing content.
|
||||
@@ -9,6 +10,11 @@ export default function Home() {
|
||||
|
||||
return (
|
||||
<div className="space-y-8 max-w-6xl mx-auto">
|
||||
<Seo
|
||||
title={t("seo.home.title")}
|
||||
description={t("seo.home.description")}
|
||||
path="/"
|
||||
/>
|
||||
{/* Page Header */}
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-bold text-gray-900 sm:text-4xl">{t("home.title")}</h1>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useMemo, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import JsonCodeEditor from "@/components/json-code-editor"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
type RowRecord = Record<string, unknown>
|
||||
|
||||
@@ -79,6 +80,11 @@ export default function JsonGrid() {
|
||||
|
||||
return (
|
||||
<div className="h-full flex gap-4 overflow-hidden">
|
||||
<Seo
|
||||
title={t("seo.jsonGrid.title")}
|
||||
description={t("seo.jsonGrid.description")}
|
||||
path="/json-grid"
|
||||
/>
|
||||
<div className="w-[35%] bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden flex flex-col min-h-0">
|
||||
<div className="bg-slate-50 px-4 py-2 border-b border-slate-200 shrink-0">
|
||||
<span className="text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next"
|
||||
import jp from "jsonpath"
|
||||
import JsonTreeNode from "@/components/json-tree-node"
|
||||
import JsonCodeEditor from "@/components/json-code-editor"
|
||||
import Seo from "@/components/seo"
|
||||
|
||||
/**
|
||||
* JSON Viewer page component that displays the JSON visualisation tool in DevLab.
|
||||
@@ -91,6 +92,11 @@ export default function JsonViewer() {
|
||||
|
||||
return (
|
||||
<div className="h-full flex gap-4 overflow-hidden">
|
||||
<Seo
|
||||
title={t("seo.jsonViewer.title")}
|
||||
description={t("seo.jsonViewer.description")}
|
||||
path="/json-viewer"
|
||||
/>
|
||||
{/* Left panel - 30% */}
|
||||
<div className="w-[30%] flex flex-col gap-4 min-h-0">
|
||||
{/* JSON Source - fills remaining height */}
|
||||
|
||||
Reference in New Issue
Block a user