forked from retoor/devplacepy
feat: add canonical redirect, og_image, next_page_url, and sitemap caching across content routers
Implement canonical_redirect helper in content.py to enforce slug-based 301 redirects for gist, news, post, and project detail pages. Add first_image_url helper to extract primary image from item or attachments for Open Graph meta tags. Inject next_page_url into feed, gists, news, and projects list page SEO contexts for pagination link rel. Extend seo.py with SITEMAP_URL_LIMIT, SITEMAP_TTL constants and _sitemap cache variable for future sitemap generation optimization. Update profile page to raise 404 via not_found instead of 302 redirect, and include og_image from avatar_url.
This commit is contained in:
@@ -4,10 +4,10 @@ from fastapi import APIRouter, Request, Form
|
||||
from devplacepy.models import GistForm, GistEditForm
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from devplacepy.database import get_table, get_users_by_uids, get_gist_languages, paginate
|
||||
from devplacepy.content import load_detail, edit_content_item, delete_content_item, enrich_items, create_content_item, detail_context
|
||||
from devplacepy.content import load_detail, edit_content_item, delete_content_item, enrich_items, create_content_item, detail_context, canonical_redirect, first_image_url
|
||||
from devplacepy.templating import templates
|
||||
from devplacepy.utils import get_current_user, require_user, not_found, XP_GIST
|
||||
from devplacepy.seo import base_seo_context, site_url, website_schema, software_source_code_schema, list_page_seo
|
||||
from devplacepy.seo import base_seo_context, site_url, website_schema, software_source_code_schema, list_page_seo, next_page_url
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
@@ -53,6 +53,7 @@ async def gists_page(request: Request, language: str = None, user_uid: str = Non
|
||||
{"name": "Home", "url": "/feed"},
|
||||
{"name": "Gists", "url": "/gists"},
|
||||
],
|
||||
next_url=next_page_url(request, next_cursor),
|
||||
)
|
||||
return templates.TemplateResponse(request, "gists.html", {
|
||||
**seo_ctx,
|
||||
@@ -74,6 +75,9 @@ async def gist_detail(request: Request, gist_slug: str):
|
||||
if not detail:
|
||||
raise not_found("Gist not found")
|
||||
gist = detail["item"]
|
||||
redirect = canonical_redirect("gists", gist, gist_slug)
|
||||
if redirect:
|
||||
return redirect
|
||||
|
||||
base = site_url(request)
|
||||
seo_ctx = base_seo_context(
|
||||
@@ -81,6 +85,7 @@ async def gist_detail(request: Request, gist_slug: str):
|
||||
title=gist.get("title", "Gist"),
|
||||
description=gist.get("description", "")[:160],
|
||||
og_type="article",
|
||||
og_image=first_image_url(gist, detail["attachments"]),
|
||||
breadcrumbs=[
|
||||
{"name": "Home", "url": "/feed"},
|
||||
{"name": "Gists", "url": "/gists"},
|
||||
|
||||
Reference in New Issue
Block a user