feat: enhance SEO and add multilingual support with new meta tags and sitemap

This commit is contained in:
Cheick Oumar 2026-05-20 13:31:45 +02:00
commit 37f3e1ecea
6 changed files with 101 additions and 1 deletions

View file

@ -1,5 +1,6 @@
--- ---
title: "Home" title: "Home"
description: "TheAfriForge is the African foundation for free software and digital sovereignty. Open source projects, open governance and continental infrastructure."
hero: hero:
kicker: "African digital infrastructure" kicker: "African digital infrastructure"
titleLine1: "Free and sovereign" titleLine1: "Free and sovereign"

View file

@ -1,5 +1,6 @@
--- ---
title: "Accueil" title: "Accueil"
description: "TheAfriForge est la fondation africaine du logiciel libre et de la souveraineté numérique. Projets open source, gouvernance ouverte et infrastructure continentale."
hero: hero:
kicker: "Infrastructure numérique africaine" kicker: "Infrastructure numérique africaine"
titleLine1: "L'infrastructure libre" titleLine1: "L'infrastructure libre"

View file

@ -10,6 +10,8 @@ disableAliases = true
organization = "TheAfriForge" organization = "TheAfriForge"
gitforgeUrl = "https://gitforge.africa" gitforgeUrl = "https://gitforge.africa"
repositoryUrl = "https://github.com/theafriforge" repositoryUrl = "https://github.com/theafriforge"
twitterHandle = "@theafriforge"
ogImage = "/images/og-theafriforge.png"
# Membership form configuration (fallback values). # Membership form configuration (fallback values).
# Priority used in templates: # Priority used in templates:
# 1) HUGO_MEMBERSHIP_FORM_ACTION / HUGO_MEMBERSHIP_FORM_SUCCESS_PATH # 1) HUGO_MEMBERSHIP_FORM_ACTION / HUGO_MEMBERSHIP_FORM_SUCCESS_PATH
@ -18,6 +20,11 @@ disableAliases = true
membershipFormAction = "" membershipFormAction = ""
membershipFormSuccessPath = "" membershipFormSuccessPath = ""
[sitemap]
changeFreq = "weekly"
filename = "sitemap.xml"
priority = 0.5
[languages] [languages]
[languages.fr] [languages.fr]
languageName = "Français" languageName = "Français"

View file

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} | {{ .Site.Title }}{{ end }}</title> <title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} | {{ .Site.Title }}{{ end }}</title>
<meta name="description" content="{{ i18n "siteDescription" }}"> {{ partial "seo.html" . }}
<script> <script>
tailwind = { tailwind = {
config: { config: {

85
layouts/partials/seo.html Normal file
View file

@ -0,0 +1,85 @@
{{/* ---- Resolved values ---- */}}
{{ $title := cond .IsHome .Site.Title (printf "%s | %s" .Title .Site.Title) }}
{{ $description := or .Description (i18n "siteDescription") }}
{{ $url := .Permalink }}
{{ $lang := .Site.Language.Lang }}
{{ $locale := replace .Site.LanguageCode "-" "_" }}
{{/* ---- Canonical ---- */}}
<link rel="canonical" href="{{ $url }}">
{{/* ---- Meta robots ---- */}}
{{ if or .Params.noindex .Draft }}
<meta name="robots" content="noindex, nofollow">
{{ else }}
<meta name="robots" content="index, follow">
{{ end }}
{{/* ---- Meta description ---- */}}
{{ with $description }}
<meta name="description" content="{{ . | plainify | truncate 160 }}">
{{ end }}
{{/* ---- Hreflang alternates ---- */}}
{{ range .AllTranslations }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}">
{{ end }}
{{ range .AllTranslations }}
{{ if eq .Language.Weight 1 }}
<link rel="alternate" hreflang="x-default" href="{{ .Permalink }}">
{{ end }}
{{ end }}
{{/* ---- Open Graph ---- */}}
<meta property="og:site_name" content="{{ .Site.Title }}">
<meta property="og:title" content="{{ $title }}">
<meta property="og:description" content="{{ $description | plainify | truncate 200 }}">
<meta property="og:url" content="{{ $url }}">
<meta property="og:locale" content="{{ $locale }}">
{{ if .IsHome }}
<meta property="og:type" content="website">
{{ else }}
<meta property="og:type" content="article">
{{ end }}
{{ with .Site.Params.ogImage }}
<meta property="og:image" content="{{ . | absURL }}">
{{ end }}
{{/* ---- Twitter Card ---- */}}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ $title }}">
<meta name="twitter:description" content="{{ $description | plainify | truncate 200 }}">
{{ with .Site.Params.twitterHandle }}
<meta name="twitter:site" content="{{ . }}">
{{ end }}
{{ with .Site.Params.ogImage }}
<meta name="twitter:image" content="{{ . | absURL }}">
{{ end }}
{{/* ---- JSON-LD Organization (home only) ---- */}}
{{ if .IsHome }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "{{ .Site.Title }}",
"url": "{{ .Site.BaseURL }}",
"description": "{{ i18n "siteDescription" | plainify }}",
"sameAs": [
{{ with .Site.Params.repositoryUrl }}"{{ . }}"{{ end }}
]
}
</script>
{{ end }}
{{/* ---- JSON-LD WebSite (home only — enables sitelinks search) ---- */}}
{{ if .IsHome }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "{{ .Site.Title }}",
"url": "{{ .Site.BaseURL }}"
}
</script>
{{ end }}

6
layouts/robots.txt Normal file
View file

@ -0,0 +1,6 @@
User-agent: *
Allow: /
Sitemap: {{ .Site.BaseURL }}sitemap.xml
Sitemap: {{ .Site.BaseURL }}fr/sitemap.xml
Sitemap: {{ .Site.BaseURL }}en/sitemap.xml