feat: intégration plugin Kirby SEO
All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
- Ajout de tobimori/kirby-seo via Composer
- snippet('seo/head') dans header.php (remplace les meta manuels)
- snippet('seo/schemas') dans footer.php pour JSON-LD
- Onglet SEO ajouté dans site.yml et tous les blueprints de pages
- Configuration SEO dans config.php (sitemap, robots, canonicalBase TODO)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
baab2fb3a1
commit
58c31ea391
133 changed files with 9201 additions and 253 deletions
39
site/plugins/kirby-seo/config/options/ai.php
Normal file
39
site/plugins/kirby-seo/config/options/ai.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use tobimori\Seo\Ai\Drivers\Anthropic;
|
||||
use tobimori\Seo\Ai\Drivers\Gemini;
|
||||
use tobimori\Seo\Ai\Drivers\OpenAi;
|
||||
|
||||
// TODO: custom provider per task
|
||||
return [
|
||||
'enabled' => true,
|
||||
'provider' => 'openai',
|
||||
'providers' => [
|
||||
'openai' => [
|
||||
'driver' => OpenAi::class,
|
||||
'config' => [
|
||||
'apiKey' => '', // needs to be defined
|
||||
],
|
||||
],
|
||||
'anthropic' => [
|
||||
'driver' => Anthropic::class,
|
||||
'config' => [
|
||||
'apiKey' => '', // needs to be defined
|
||||
],
|
||||
],
|
||||
'gemini' => [
|
||||
'driver' => Gemini::class,
|
||||
'config' => [
|
||||
'apiKey' => '', // needs to be defined
|
||||
],
|
||||
],
|
||||
'openrouter' => [
|
||||
'driver' => OpenAi::class,
|
||||
'config' => [
|
||||
'apiKey' => '', // needs to be defined
|
||||
'model' => 'openai/gpt-5-nano',
|
||||
'endpoint' => 'https://openrouter.ai/api/v1/responses',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
29
site/plugins/kirby-seo/config/options/indexnow.php
Normal file
29
site/plugins/kirby-seo/config/options/indexnow.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'enabled' => true,
|
||||
'searchEngine' => 'https://api.indexnow.org', // one will propagate to all others. so this is fine @see https://www.indexnow.org/faq
|
||||
'rules' => [
|
||||
// by default, only the current page is requested to be indexed (if indexable: robots allow + listed status)
|
||||
// however you might want to index other pages as well. for example, the 'blog overview' page should always be reindexed when a new 'blog post' is indexed
|
||||
//
|
||||
// syntax: 'match pattern' => ['invalidation rules']
|
||||
//
|
||||
// match patterns:
|
||||
// - '/blog/*' - url pattern (glob or regex)
|
||||
// - 'article' - template name
|
||||
// - '*' - wildcard, matches all pages
|
||||
//
|
||||
// invalidation rules:
|
||||
// - 'parent' => true (direct parent) or number (levels up)
|
||||
// - 'children' => true (all descendants) or number (depth limit)
|
||||
// - 'siblings' => true (all siblings at same level)
|
||||
// - 'urls' => ['/shop', '/'] (specific urls to invalidate)
|
||||
// - 'templates' => ['category', 'shop'] (invalidate all pages with these templates)
|
||||
//
|
||||
// examples:
|
||||
// '/blog/*' => ['parent' => true],
|
||||
// 'article' => ['parent' => 2, 'urls' => ['/blog', '/']],
|
||||
// 'product' => ['parent' => true, 'siblings' => true, 'templates' => ['category']],
|
||||
],
|
||||
];
|
||||
55
site/plugins/kirby-seo/config/options/sitemap.php
Normal file
55
site/plugins/kirby-seo/config/options/sitemap.php
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
use tobimori\Seo\Sitemap\SitemapIndex;
|
||||
use tobimori\Seo\Meta;
|
||||
|
||||
return function (SitemapIndex $sitemap) {
|
||||
$exclude = option('tobimori.seo.sitemap.excludeTemplates', []);
|
||||
$pages = site()->index()->filter(fn ($page) => $page->metadata()->robotsIndex()->toBool() && !in_array($page->intendedTemplate()->name(), $exclude));
|
||||
|
||||
if ($group = option('tobimori.seo.sitemap.groupByTemplate')) {
|
||||
$pages = $pages->group('intendedTemplate');
|
||||
}
|
||||
|
||||
if (is_a($pages->first(), 'Kirby\Cms\Page')) {
|
||||
$pages = $pages->group(fn () => 'pages');
|
||||
}
|
||||
|
||||
foreach ($pages as $group) {
|
||||
$index = $sitemap->create($group ? $group->first()->intendedTemplate()->name() : 'pages');
|
||||
|
||||
foreach ($group as $page) {
|
||||
$url = $index->createUrl($page->metadata()->canonicalUrl())
|
||||
->lastmod($page->modified() ?? (int)(date('c')))
|
||||
->changefreq(is_callable($changefreq = option('tobimori.seo.sitemap.changefreq')) ? $changefreq($page) : $changefreq)
|
||||
->priority(is_callable($priority = option('tobimori.seo.sitemap.priority')) ? $priority($page) : $priority);
|
||||
|
||||
if (kirby()->languages()->count() > 1 && kirby()->language() !== null) {
|
||||
$alternates = [];
|
||||
foreach (kirby()->languages() as $language) {
|
||||
// only if this language is translated for this page and exists
|
||||
if ($page->translation($language->code())->exists()) {
|
||||
/*
|
||||
* Specification: "lists every alternate version of the page, including itself."
|
||||
* https://developers.google.com/search/docs/specialty/international/localized-versions#sitemap
|
||||
*/
|
||||
$alternates[] =
|
||||
[
|
||||
'hreflang' => Meta::toBCP47($language),
|
||||
'href' => $page->url($language->code()),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// add x-default
|
||||
$alternates[] =
|
||||
[
|
||||
'hreflang' => 'x-default',
|
||||
'href' => $page->indexUrl(),
|
||||
];
|
||||
|
||||
$url->alternates($alternates);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue