Skip to content

PageMeta

PageMeta is a higher-level head composer that combines SEO tags, canonical URL handling, optional PWA tags, and optional favicon links in one call.

It is designed for teams that want a single, predictable entry point for page head metadata without repeating multiple helpers.

Import

from faststrap import PageMeta

What problem it solves

  • Prevents accidental duplicate/conflicting tags in route-level code.
  • Reduces repetitive SEO(...) + PwaMeta(...) + favicon links assembly.
  • Makes head management easier for new contributors.

Basic usage (SEO + canonical)

PageMeta(
    title="Faststrap Docs",
    description="Build modern UI in Python",
    canonical="https://faststrap.dev/docs",
    image="https://faststrap.dev/og/docs.png",
)

Include PWA tags

PageMeta(
    title="My App",
    description="Installable FastHTML app",
    include_pwa=True,
    pwa_name="My App",
    pwa_short_name="MyApp",
    pwa_theme_color="#0d6efd",
)
PageMeta(
    title="Dashboard",
    favicon_url="/assets/favicon.png",
)

Real route example

@app.get("/")
def home():
    return (
        PageMeta(title="Home", description="Welcome"),
        Container(H1("Home")),
    )

SEO vs PageMeta (important)

Use SEO(...) when:

  • You only need SEO/social tags.
  • You want complete manual control.
  • You are building your own composition layer.

Use PageMeta(...) when:

  • You want one helper for SEO + canonical + optional PWA/favicon.
  • You want dedupe behavior to reduce head conflicts.
  • You want a cleaner onboarding experience for app teams.

Decision guide

  • Simple content page: SEO(...) is enough.
  • Marketing/app shell pages with installability/favicons: prefer PageMeta(...).
  • Large codebase with many routes/layouts: prefer PageMeta(...) for consistency.

Common use cases

  1. Blog/article routes that need social previews and canonical.
  2. Product/detail routes that need share-ready metadata with minimal boilerplate.
  3. PWA-ready pages that need head tags in one place.

API reference summary

  • SEO-related: title, description, keywords, image, url, canonical, robots, twitter_site, twitter_creator, locale.
  • PWA-related: include_pwa, pwa_name, pwa_short_name, pwa_theme_color, pwa_background_color.
  • Assets/meta extras: favicon_url, extra_meta.

Notes

  • PageMeta(...) is additive convenience, not a replacement for advanced StructuredData usage.
  • For JSON-LD schema, keep using StructuredData.*(...) alongside PageMeta(...).
  • Canonical links are emitted only when canonical or url is provided.

API Reference

faststrap.seo.page_meta.PageMeta(title=None, description=None, keywords=None, image=None, url=None, canonical=None, type='website', robots='index, follow', twitter_site=None, twitter_creator=None, locale=None, include_pwa=False, pwa_name=None, pwa_short_name=None, pwa_theme_color='#ffffff', pwa_background_color='#ffffff', favicon_url=None, extra_meta=None)

Compose page metadata with deduplication guarantees.

Source code in src/faststrap/seo/page_meta.py
def PageMeta(
    title: str | None = None,
    description: str | None = None,
    keywords: list[str] | None = None,
    image: str | None = None,
    url: str | None = None,
    canonical: str | None = None,
    type: Literal["website", "article", "product"] = "website",
    robots: str = "index, follow",
    twitter_site: str | None = None,
    twitter_creator: str | None = None,
    locale: str | None = None,
    include_pwa: bool = False,
    pwa_name: str | None = None,
    pwa_short_name: str | None = None,
    pwa_theme_color: str = "#ffffff",
    pwa_background_color: str = "#ffffff",
    favicon_url: str | None = None,
    extra_meta: dict[str, Any] | None = None,
) -> tuple[Any, ...]:
    """Compose page metadata with deduplication guarantees."""
    elements: list[Any] = []

    if title is not None:
        elements.append(Title(title))
    elements.extend(
        SEO(
            title=title,
            description=description,
            keywords=keywords,
            image=image,
            url=url,
            canonical=canonical,
            og_type=type,
            robots=robots,
            twitter_site=twitter_site,
            twitter_creator=twitter_creator,
            locale=locale,
        )
    )

    if include_pwa:
        elements.extend(
            PwaMeta(
                name=pwa_name or title or "Faststrap App",
                short_name=pwa_short_name or pwa_name or "Faststrap",
                description=description,
                theme_color=pwa_theme_color,
                background_color=pwa_background_color,
            )
        )

    if favicon_url:
        elements.extend(create_favicon_links(favicon_url))

    if extra_meta:
        for key, value in extra_meta.items():
            if value is None:
                continue
            attr = key.replace("_", "-")
            elements.append(Meta(name=attr, content=str(value)))

    canonical_url = canonical or url
    if canonical_url:
        elements.append(Link(rel="canonical", href=canonical_url))

    return _dedupe(elements)