feat: add seo_meta service for AI-generated SEO metadata with CLI management and database layer

Implement a new `SeoMetaService` subservice that generates clean SEO title/description/keywords for published content items, distinct from the existing SEO diagnostics auditor. Add `seo_metadata` polymorphic table with soft-delete support, batch query methods, and usage tracking. Extend the CLI with `seo-meta prune` and `seo-meta clear` commands for job row lifecycle management. Wire `schedule_seo_meta_for_table` into content creation and editing flows in `content.py`. Document the new service in `AGENTS.md` and `README.md`, including the `extra_head` site setting for custom `<head>` injection.
This commit is contained in:
2026-06-19 20:15:22 +00:00
parent 426d3639c6
commit d10f1af118
51 changed files with 2262 additions and 93 deletions
+8
View File
@@ -11,12 +11,18 @@
{% if prev_url %}<link rel="prev" href="{{ prev_url }}">{% endif %}
{% if next_url %}<link rel="next" href="{{ next_url }}">{% endif %}
<meta name="robots" content="{{ meta_robots or 'index,follow' }}">
{% if meta_keywords %}<meta name="keywords" content="{{ meta_keywords }}">{% endif %}
<meta property="og:title" content="{{ og_title or page_title or 'DevPlace' }}">
<meta property="og:description" content="{{ og_description or meta_description or 'The Developer Social Network' }}">
<meta property="og:type" content="{{ og_type or 'website' }}">
<meta property="og:url" content="{{ canonical_url or request.url }}">
<meta property="og:image" content="{{ static_url(og_image or '/static/og-default.png') }}">
{% if not og_image or og_image == '/static/og-default.png' %}
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
{% endif %}
<meta property="og:image:alt" content="{{ og_title or page_title or 'DevPlace' }}">
<meta property="og:site_name" content="DevPlace">
<meta property="og:locale" content="en_US">
@@ -24,6 +30,7 @@
<meta name="twitter:title" content="{{ og_title or page_title or 'DevPlace' }}">
<meta name="twitter:description" content="{{ og_description or meta_description or 'The Developer Social Network' }}">
<meta name="twitter:image" content="{{ static_url(og_image or '/static/og-default.png') }}">
<meta name="twitter:image:alt" content="{{ og_title or page_title or 'DevPlace' }}">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>&#x1f4bb;</text></svg>">
<link rel="apple-touch-icon" href="{{ static_url('/static/apple-touch-icon.png') }}">
@@ -45,6 +52,7 @@
<link rel="stylesheet" href="{{ static_url('/static/css/engagement.css') }}">
{% block extra_head %}{% endblock %}
{{ custom_css_tag(request) }}
{{ extra_head_tag() }}
{% if page_schema %}
<script type="application/ld+json">