🔍 SEO & Sitemaps

Generate meta tags, sitemaps, and structured data for search engines.

🎯 Overview

Function Purpose
generate_head_tags Meta tags for social sharing
generate_sitemap_xml XML sitemap for crawlers
generate_json_ld Structured data (Article schema)

🏷️ Meta Tags

Function Purpose
generate_head_tags OpenGraph, Twitter Card, canonical

source

generate_head_tags


def generate_head_tags(
    title:str, # Page title
    description:str, # Page description (150-160 chars optimal)
    url:str, # Canonical URL
    image_url:Optional[str]=None, # OpenGraph image URL
    article_published:Optional[datetime]=None, # Publication date
    article_modified:Optional[datetime]=None, # Last modified date
    author:Optional[str]=None, # Author name
)->List[tuple]:

Generate meta tags for SEO.

Returns list of (tag_name, attributes_dict) tuples for FastHTML components. Includes standard, OpenGraph, and Twitter Card tags.

Example: ```python from fasthtml.common import *

tags = generate_head_tags(
    title='My Blog Post',
    description='Learn about Python',
    url='https://example.com/blog/my-post',
    image_url='https://example.com/image.jpg'
)

# Use in FastHTML app
@app.get('/blog/my-post')
def post():
    return Html(
        Head(
            *[Meta(**attrs) if tag == 'meta' else Link(**attrs) 
              for tag, attrs in tags]
        ),
        Body('...')
    )
```

🗺️ Sitemap

Function Purpose
generate_sitemap_xml XML sitemap for search crawlers

source

generate_sitemap_xml


def generate_sitemap_xml(
    posts:List[Dict], # List of posts from PostLoader
    base_url:str, # Base URL (e.g., 'https://example.com')
    blog_path:str='/blog', # Blog path prefix
)->str:

Generate XML sitemap for blog posts.

Returns sitemap XML string with proper structure and lastmod dates.

Example: ```python from fasthtml.common import * from fh_saas.utils_blog import PostLoader

app = FastHTML()
loader = PostLoader('blog/posts')

@app.get('/sitemap.xml')
def sitemap():
    posts = loader.load_posts()
    xml = generate_sitemap_xml(
        posts=posts,
        base_url='https://example.com',
        blog_path='/blog'
    )
    return Response(xml, media_type='application/xml')
```

rss feed generator

Generate RSS 2.0 feed for blog subscribers.


source

generate_rss_xml


def generate_rss_xml(
    posts:List[Dict], # List of posts from PostLoader
    blog_title:str, # Blog title
    blog_description:str, # Blog description
    base_url:str, # Base URL
    blog_path:str='/blog', # Blog path prefix
)->str:

Generate RSS 2.0 feed for blog posts.

Returns RSS XML string for feed readers (Feedly, etc.).

Example: ```python from fasthtml.common import * from fh_saas.utils_blog import PostLoader

app = FastHTML()
loader = PostLoader('blog/posts')

@app.get('/rss.xml')
def rss():
    posts = loader.load_posts()[:20]  # Latest 20 posts
    xml = generate_rss_xml(
        posts=posts,
        blog_title='My Blog',
        blog_description='Tech tutorials and insights',
        base_url='https://example.com'
    )
    return Response(xml, media_type='application/xml')
```

FastHTML Integration Example

Complete SEO setup with FastHTML:

from fasthtml.common import *
from fh_saas.utils_blog import PostLoader, MarkdownEngine
from fh_saas.utils_seo import generate_head_tags, generate_sitemap_xml, generate_rss_xml

app = FastHTML()
loader = PostLoader('blog/posts')
engine = MarkdownEngine()

@app.get('/blog/{slug}')
def blog_post(slug: str):
    post = loader.get_post(slug)
    if not post:
        return 'Post not found', 404
    
    # Generate SEO tags
    tags = generate_head_tags(
        title=post['title'],
        description=post['description'] or post['body'][:160],
        url=f"https://example.com/blog/{slug}",
        image_url=post.get('image'),
        article_published=post['date'],
        author=post.get('author')
    )
    
    # Render markdown
    html_content = engine.render(post['body'])
    
    return Html(
        Head(
            Title(post['title']),
            *[Meta(**attrs) if tag == 'meta' else Link(**attrs) 
              for tag, attrs in tags]
        ),
        Body(
            Article(NotStr(html_content))
        )
    )

@app.get('/sitemap.xml')
def sitemap():
    posts = loader.load_posts()
    xml = generate_sitemap_xml(posts, 'https://example.com')
    return Response(xml, media_type='application/xml')

@app.get('/rss.xml')
def rss():
    posts = loader.load_posts()[:20]
    xml = generate_rss_xml(
        posts=posts,
        blog_title='My Blog',
        blog_description='Tech tutorials',
        base_url='https://example.com'
    )
    return Response(xml, media_type='application/xml')