Improve SEO content

This commit is contained in:
kbe
2025-08-19 10:20:34 +02:00
parent 686ece4479
commit 1ea47eb2da
13 changed files with 425 additions and 5 deletions

BIN
assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
assets/images/og-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
assets/images/og-logo.xcf Normal file

Binary file not shown.

114
docs/SEO-IMPROVEMENTS.md Normal file
View File

@@ -0,0 +1,114 @@
# SEO Improvements Documentation
## Overview
This project has been enhanced with comprehensive SEO capabilities using a modular partial system in Hugo.
## File Structure
```
layouts/partials/seo/
├── seo-config.html # Main SEO configuration loader
├── seo-meta.html # Core SEO meta tags
├── opengraph.html # Open Graph tags for social media
├── twitter-cards.html # Twitter Card tags
├── structured-data.html # JSON-LD schema markup
└── favicons.html # Favicon variations and PWA support
```
## Features Added
### 1. Core SEO Meta Tags
- Dynamic meta description
- Keywords (with fallback)
- Author information
- Canonical URLs
- Robots meta tags
- Dublin Core metadata
- Geo tags (if configured)
### 2. Open Graph Tags
- og:title, og:description, og:image
- og:type (article/website)
- og:site_name
- og:url
- Article-specific tags for blog posts
### 3. Twitter Cards
- twitter:card (summary_large_image)
- twitter:title, twitter:description
- twitter:image
- Site and creator handles
### 4. Structured Data (JSON-LD)
- WebSite schema
- Article schema for blog posts
- BreadcrumbList schema
- Organization schema
### 5. Favicon & PWA Support
- Multiple favicon sizes
- Apple Touch Icons
- Android icons
- PWA manifest.json
- Theme colors
## Configuration
### Hugo Configuration (hugo.toml)
```toml
[params.seo]
description = "Your site description"
keywords = ["keyword1", "keyword2"]
author = "Your Name"
theme_color = "#007bff"
default_image = "/images/og-default.jpg"
logo = "/images/logo.png"
[params.seo.twitter]
site = "@yourhandle"
creator = "@yourhandle"
```
### Content Frontmatter
Add to your content's frontmatter:
```yaml
---
title: "Your Post Title"
description: "Detailed description for SEO"
keywords: ["seo", "hugo", "optimization"]
author: "Author Name"
image: "/images/post-image.jpg"
robots: "index, follow"
---
```
## Testing & Validation
### Recommended Tools
- Google Rich Results Test: https://search.google.com/test/rich-results
- Facebook Sharing Debugger: https://developers.facebook.com/tools/debug/
- Twitter Card Validator: https://cards-dev.twitter.com/validator
- Schema.org Validator: https://validator.schema.org/
### Validation Checklist
- [ ] Meta tags present in page source
- [ ] Open Graph tags validate
- [ ] Twitter Cards validate
- [ ] JSON-LD schema validates
- [ ] Favicons load correctly
- [ ] Canonical URLs are correct
## Next Steps
1. Generate favicon files for all sizes (use a favicon generator)
2. Create og-default.jpg and twitter-default.jpg images
3. Set up Google Search Console and add verification code
4. Set up Bing Webmaster Tools
5. Test with social media sharing
## Fallback Values
The system includes intelligent fallback values:
- Description: Page → Site → Title
- Keywords: Page → Site → Empty string
- Image: Page → Site → Default
- Author: Page → Site → Site Title
All SEO improvements have been successfully implemented!

View File

@@ -13,6 +13,32 @@ ignoreLogs = ["warning-goldmark-raw-html"]
[markup.goldmark.renderer]
unsafe = true
# SEO Configuration
[params.seo]
description = "Mistergeek - Tutoriels et guides en informatique"
keywords = ["développement web", "technologies", "innovation", "solutions digitales", "mistergeek"]
author = "Mistergeek"
theme_color = "#007bff"
default_image = "/assets/images/og-logo.png"
logo = "/assets/images/logo.png"
# Social Media
[params.seo.twitter]
site = "@mistergeekfrance"
creator = "@mistergeekfrance"
# Search Engine Verification
# google_verification = "your-google-verification-code"
# bing_verification = "your-bing-verification-code"
# yandex_verification = "your-yandex-verification-code"
# Geo Location (if applicable)
# [params.seo.geo]
# region = "FR-IDF"
# placename = "Paris"
# latitude = "48.8566"
# longitude = "2.3522"
# WordPress API Configuration
[params.wordpress]
apiUrl = "https://www.mistergeek.net/wp-json/wp/v2"
@@ -31,3 +57,20 @@ ignoreLogs = ["warning-goldmark-raw-html"]
[[build.cachebusters]]
source = "assets/.*\\.(css|sass|scss)$"
target = "css"
# Output formats for search index
[outputs]
home = ["HTML", "RSS", "JSON"]
[outputFormats]
[outputFormats.JSON]
mediaType = "application/json"
baseName = "search-index"
isPlainText = true
notAlternative = true
# Search configuration
[params.search]
enabled = true
minQueryLength = 2
maxResults = 10

View File

@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<html lang="{{ .Site.Language.Lang | default "en" }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="{{ if .Description }}{{ .Description }}{{ else }}{{ .Site.Title }}{{ end }}">
<meta name="keywords" content="">
<!-- SEO & Social Meta Tags -->
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} - {{ .Site.Title }}{{ end }}</title>
<!-- Favicon -->
<link href="/assets/images/favicon.png" rel="shortcut icon">
{{ partial "seo/seo-config.html" . }}
<!-- CSS -->
<link href="/assets/plugins/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="/assets/plugins/owl-carousel/owl.carousel.min.css" rel="stylesheet">
@@ -68,5 +68,6 @@
<script src="/assets/plugins/jquery.min.js"></script>
<script src="/assets/plugins/plugins.js"></script>
<script src="/assets/js/functions.js"></script>
{{ partial "scripts.html" . }}
</body>
</html>

View File

@@ -0,0 +1,3 @@
<!-- Search Scripts -->
<script src="https://cdn.jsdelivr.net/npm/lunr@2.3.9/lunr.min.js"></script>
<script src="/assets/js/search.js"></script>

View File

@@ -0,0 +1,32 @@
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
<link rel="shortcut icon" type="image/x-icon" href="/assets/images/favicon.ico">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" sizes="57x57" href="/assets/images/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/images/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/images/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/images/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/images/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/images/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/images/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-touch-icon-180x180.png">
<!-- Android Icons -->
<link rel="icon" type="image/png" sizes="192x192" href="/assets/images/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
<meta name="msapplication-TileImage" content="/assets/images/ms-icon-144x144.png">
<meta name="msapplication-config" content="/assets/images/browserconfig.xml">
<!-- PWA Manifest -->
<link rel="manifest" href="/manifest.json">
<!-- Theme Color -->
<meta name="theme-color" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">

View File

@@ -0,0 +1,33 @@
{{- $title := .Title | default .Site.Title -}}
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/og-default.jpg" -}}
{{- $image = $image | absURL -}}
{{- $url := .Permalink | default .RelPermalink | absURL -}}
{{- $siteName := .Site.Title -}}
{{- $locale := .Site.Language.Lang | default "en_US" -}}
<!-- Open Graph / Facebook -->
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
<meta property="og:site_name" content="{{ $siteName }}">
<meta property="og:title" content="{{ $title }}">
<meta property="og:description" content="{{ $description }}">
<meta property="og:url" content="{{ $url }}">
<meta property="og:locale" content="{{ $locale }}">
<meta property="og:image" content="{{ $image }}">
<meta property="og:image:alt" content="{{ $title }}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Article specific -->
{{ if .IsPage }}
<meta property="article:section" content="{{ .Section | default "general" }}">
<meta property="article:author" content="{{ .Params.author | default .Site.Params.author | default .Site.Title }}">
{{ range .Params.tags | default .Site.Params.tags }}
<meta property="article:tag" content="{{ . }}">
{{ end }}
{{ end }}
<!-- Additional locales for multilingual sites -->
{{ range .Translations }}
<meta property="og:locale:alternate" content="{{ .Language.Lang | default "en_US" }}">
{{ end }}

View File

@@ -0,0 +1,42 @@
{{- /* SEO Configuration Partial */ -}}
{{- /* This partial includes all SEO-related partials */ -}}
<!-- Core SEO Meta Tags -->
{{ partial "seo/seo-meta.html" . }}
<!-- Open Graph Tags -->
{{ partial "seo/opengraph.html" . }}
<!-- Twitter Cards -->
{{ partial "seo/twitter-cards.html" . }}
<!-- Structured Data (JSON-LD) -->
{{ partial "seo/structured-data.html" . }}
<!-- Favicons and PWA Support -->
{{ partial "seo/favicons.html" . }}
<!-- Additional SEO Tags -->
{{- if .Site.Params.seo.google_verification }}
<meta name="google-site-verification" content="{{ .Site.Params.seo.google_verification }}">
{{ end }}
{{- if .Site.Params.seo.bing_verification }}
<meta name="msvalidate.01" content="{{ .Site.Params.seo.bing_verification }}">
{{ end }}
{{- if .Site.Params.seo.yandex_verification }}
<meta name="yandex-verification" content="{{ .Site.Params.seo.yandex_verification }}">
{{ end }}
{{- if .Site.Params.seo.alexa_verification }}
<meta name="alexaVerifyID" content="{{ .Site.Params.seo.alexa_verification }}">
{{ end }}
<!-- hreflang for multilingual sites -->
{{ range .Translations }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}">
{{ end }}
{{ if .IsTranslated }}
<link rel="alternate" hreflang="x-default" href="{{ .Permalink }}">
{{ end }}

View File

@@ -0,0 +1,40 @@
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $keywords := delimit (.Keywords | default .Site.Params.keywords | default (slice)) ", " -}}
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title -}}
{{- $robots := .Params.robots | default "index, follow" -}}
{{- $canonical := .Permalink | default .RelPermalink -}}
<!-- Primary Meta Tags -->
<meta name="description" content="{{ $description }}">
<meta name="keywords" content="{{ $keywords }}">
<meta name="author" content="{{ $author }}">
<meta name="robots" content="{{ $robots }}">
<meta name="generator" content="Hugo {{ hugo.Version }}">
<!-- Canonical URL -->
<link rel="canonical" href="{{ $canonical }}">
<!-- Theme Color -->
<meta name="theme-color" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
<!-- Additional SEO -->
<meta name="rating" content="general">
<meta name="language" content="{{ .Site.Language.Lang | default "en" }}">
<meta name="revisit-after" content="7 days">
<meta name="distribution" content="global">
<meta name="web_author" content="{{ .Site.Params.author | default .Site.Title }}">
<!-- Geo Tags (if location is specified) -->
{{ with .Site.Params.seo.geo }}
<meta name="geo.region" content="{{ .region }}">
<meta name="geo.placename" content="{{ .placename }}">
<meta name="geo.position" content="{{ .latitude }};{{ .longitude }}">
<meta name="ICBM" content="{{ .latitude }}, {{ .longitude }}">
{{ end }}
<!-- Dublin Core -->
<meta name="DC.Title" content="{{ .Title | default .Site.Title }}">
<meta name="DC.Creator" content="{{ $author }}">
<meta name="DC.Description" content="{{ $description }}">
<meta name="DC.Language" content="{{ .Site.Language.Lang | default "en" }}">

View File

@@ -0,0 +1,85 @@
{{- $title := .Title | default .Site.Title -}}
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/logo.png" -}}
{{- $image = $image | absURL -}}
{{- $url := .Permalink | default .RelPermalink | absURL -}}
{{- $siteName := .Site.Title -}}
{{- $logo := .Site.Params.seo.logo | default "/assets/images/logo.png" | absURL -}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "{{ $siteName }}",
"description": "{{ $description }}",
"url": "{{ .Site.BaseURL }}",
"logo": {
"@type": "ImageObject",
"url": "{{ $logo }}"
}
}
</script>
{{ if .IsPage }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "{{ $title }}",
"description": "{{ $description }}",
"image": "{{ $image }}",
"url": "{{ $url }}",
"author": {
"@type": "Person",
"name": "{{ .Params.author | default .Site.Params.author | default .Site.Title }}"
},
"publisher": {
"@type": "Organization",
"name": "{{ $siteName }}",
"logo": {
"@type": "ImageObject",
"url": "{{ $logo }}"
}
}
}
</script>
{{ end }}
<!-- Breadcrumb Schema -->
{{ if and .IsPage .Section }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Accueil",
"item": "{{ .Site.BaseURL }}"
}
{{ if .Section }}
,{
"@type": "ListItem",
"position": 2,
"name": "{{ .Section | humanize }}",
"item": "{{ .Site.BaseURL }}{{ .Section }}/"
}
,{
"@type": "ListItem",
"position": 3,
"name": "{{ $title }}",
"item": "{{ $url }}"
}
{{ else }}
,{
"@type": "ListItem",
"position": 2,
"name": "{{ $title }}",
"item": "{{ $url }}"
}
{{ end }}
]
}
</script>
{{ end }}

View File

@@ -0,0 +1,27 @@
{{- $title := .Title | default .Site.Title -}}
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/twitter-default.jpg" -}}
{{- $image = $image | absURL -}}
{{- $siteName := .Site.Title -}}
{{- $twitter := .Site.Params.seo.twitter -}}
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ $title }}">
<meta name="twitter:description" content="{{ $description }}">
<meta name="twitter:image" content="{{ $image }}">
<meta name="twitter:image:alt" content="{{ $title }}">
<!-- Twitter Site -->
{{ with $twitter.site }}
<meta name="twitter:site" content="{{ . }}">
{{ end }}
<!-- Twitter Creator -->
{{ with $twitter.creator }}
<meta name="twitter:creator" content="{{ . }}">
{{ else }}
{{ with .Params.author }}
<meta name="twitter:creator" content="{{ . }}">
{{ end }}
{{ end }}