From redaxo-yrewrite
Generates SEO meta tags via rex_yrewrite_seo, sitemap.xml, robots.txt, canonical and hreflang tags for YRewrite. Supports article SEO fields, Open Graph, and Twitter cards in templates.
npx claudepluginhub friendsofredaxo/claude-marketplace --plugin redaxo-yrewriteThis skill uses the workspace's default tool permissions.
YRewrite ships with `rex_yrewrite_seo` – a helper that pulls SEO data from articles (title, description, image) and renders meta tags. It also generates `sitemap.xml` and a `robots.txt` block.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Processes PDFs: extracts text/tables/images, merges/splits/rotates pages, adds watermarks, creates/fills forms, encrypts/decrypts, OCRs scans. Activates on PDF mentions or output requests.
Share bugs, ideas, or general feedback.
YRewrite ships with rex_yrewrite_seo – a helper that pulls SEO data from articles (title, description, image) and renders meta tags. It also generates sitemap.xml and a robots.txt block.
Each article has SEO fields managed via the seo tab in the backend (article edit). They live as meta-info fields:
art_yrewrite_title – <title> override (falls back to article name)art_yrewrite_description – meta descriptionart_yrewrite_index – index, noindex, or empty (default = follow site setting)art_yrewrite_canonical_url – override canonicalart_yrewrite_image – Open Graph image filenameFor domain-level defaults (site title, description), set them per domain in YRewrite → Domains → SEO.
Place this in the <head> of your template:
<?php $seo = new rex_yrewrite_seo(); ?>
<title><?= rex_escape($seo->getTitle()) ?></title>
<meta name="description" content="<?= rex_escape($seo->getDescription(), 'html_attr') ?>">
<?= $seo->getRobotsTag() ?>
<?= $seo->getCanonicalUrlTag() ?>
<?= $seo->getHreflangTags() ?>
getRobotsTag(), getCanonicalUrlTag(), and getHreflangTags() produce full <meta> / <link> elements. They're already escaped – don't wrap them in rex_escape.
YRewrite doesn't render OG tags itself. Add them yourself using the SEO data plus an explicit OG image:
<?php
$seo = new rex_yrewrite_seo();
$ogImage = (string) rex_article::getCurrent()->getValue('art_yrewrite_image');
$ogImageUrl = $ogImage
? rex::getServer() . rex_url::media($ogImage)
: rex::getServer() . rex_url::frontend('assets/og-default.jpg');
?>
<meta property="og:title" content="<?= rex_escape($seo->getTitle(), 'html_attr') ?>">
<meta property="og:description" content="<?= rex_escape($seo->getDescription(), 'html_attr') ?>">
<meta property="og:url" content="<?= rex_escape(rex_yrewrite::getFullUrlByArticleId(rex_article::getCurrentId(), rex_clang::getCurrentId()), 'html_attr') ?>">
<meta property="og:type" content="website">
<meta property="og:image" content="<?= rex_escape($ogImageUrl, 'html_attr') ?>">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="<?= rex_escape($seo->getTitle(), 'html_attr') ?>">
<meta name="twitter:description" content="<?= rex_escape($seo->getDescription(), 'html_attr') ?>">
<meta name="twitter:image" content="<?= rex_escape($ogImageUrl, 'html_attr') ?>">
YRewrite auto-generates https://<domain>/sitemap.xml. To exclude an article, set art_yrewrite_index to noindex or check "exclude from sitemap" in the backend.
To extend the sitemap with dynamic entries (e.g. YForm dataset URLs), hook into the sitemap generation:
// In your addon's boot.php
rex_extension::register('YREWRITE_SITEMAP', function (rex_extension_point $ep) {
$items = $ep->getSubject();
foreach (team_member::query()->where('status', 1)->find() as $member) {
$items[] = [
'loc' => rex_yrewrite::getFullUrlByArticleId(42, rex_clang::getCurrentId())
. '?member=' . $member->getId(),
'lastmod' => date('c', strtotime((string) $member->getValue('updatedate'))),
'changefreq' => 'monthly',
'priority' => '0.6',
];
}
return $items;
});
YRewrite serves robots.txt per domain. Configure each domain's robots block in YRewrite → Domains → robots.txt. Default content:
User-agent: *
Allow: /
Sitemap: https://www.example.com/sitemap.xml
For staging environments, swap to:
User-agent: *
Disallow: /
Detect environment in your template or boot.php and switch with an extension point if you don't want to maintain separate domain configs.
<html lang="..."> matches the active clang codegetCanonicalUrlTag())hreflang for every supported language including x-default (getHreflangTags() does this)<title> and meta description per article per languageYRewrite doesn't render JSON-LD; add it explicitly. For an article page:
<script type="application/ld+json">
<?= json_encode([
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => $seo->getTitle(),
'description' => $seo->getDescription(),
'datePublished' => date('c', rex_article::getCurrent()->getCreateDate()),
'dateModified' => date('c', rex_article::getCurrent()->getUpdateDate()),
'author' => [
'@type' => 'Organization',
'name' => rex::getServerName(),
],
'mainEntityOfPage' => rex_yrewrite::getFullUrlByArticleId(
rex_article::getCurrentId(),
rex_clang::getCurrentId()
),
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?>
</script>
getRobotsTag() / getHreflangTags() in rex_escape() – they output safe markup already. Double-escaping breaks them.art_yrewrite_canonical_url to a duplicate URL on multiple articles – Google then ignores all but one.Disallow: / in production after copying from staging.