diff options
| author | Ben Sima <ben@bsima.me> | 2025-11-15 19:14:34 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-11-15 19:14:34 -0500 |
| commit | 8c941c20542c65e7db5d81a3244232620b3c9809 (patch) | |
| tree | 0140455061ea425a5f4701feaafc9de1a9aa09dd /Biz | |
| parent | 76ef400b9b1e7fd1909905d0badd4a5a27d0d52e (diff) | |
Add Open Graph and metadata tags to episode pages
- Add page_title and meta_tags parameters to PageLayout - Generate
episode-specific page titles: '<Episode Title> - PodcastItLater' -
Add Open Graph meta tags for better link previews:
- og:title, og:type, og:url - og:description with duration and
author - og:audio with MP3 URL - og:site_name
- Add Twitter Card tags for Twitter sharing - Include article:author
when available
This improves how episode links appear when shared in messaging apps,
social media, and other platforms that support Open Graph protocol.
Amp-Thread-ID:
https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Biz')
| -rw-r--r-- | Biz/PodcastItLater/Episode.py | 40 | ||||
| -rw-r--r-- | Biz/PodcastItLater/UI.py | 7 |
2 files changed, 46 insertions, 1 deletions
diff --git a/Biz/PodcastItLater/Episode.py b/Biz/PodcastItLater/Episode.py index abcff92..a070d19 100644 --- a/Biz/PodcastItLater/Episode.py +++ b/Biz/PodcastItLater/Episode.py @@ -210,6 +210,44 @@ class EpisodeDetailPage(Component[AnyChildren, EpisodeDetailPageAttrs]): share_url = f"{base_url}/episode/{episode['id']}" duration_str = UI.format_duration(episode.get("duration")) + # Build page title + page_title = f"{episode['title']} - PodcastItLater" + + # Build meta tags for Open Graph + meta_tags = [ + html.meta(property="og:title", content=episode["title"]), + html.meta(property="og:type", content="website"), + html.meta(property="og:url", content=share_url), + html.meta( + property="og:description", + content=f"Listen to this article read aloud. " + f"Duration: {duration_str}" + + (f" by {episode['author']}" if episode.get("author") else ""), + ), + html.meta( + property="og:site_name", + content="PodcastItLater", + ), + html.meta(property="og:audio", content=episode["audio_url"]), + html.meta(property="og:audio:type", content="audio/mpeg"), + ] + + # Add Twitter Card tags + meta_tags.extend([ + html.meta(name="twitter:card", content="summary"), + html.meta(name="twitter:title", content=episode["title"]), + html.meta( + name="twitter:description", + content=f"Listen to this article. Duration: {duration_str}", + ), + ]) + + # Add author if available + if episode.get("author"): + meta_tags.append( + html.meta(property="article:author", content=episode["author"]), + ) + return UI.PageLayout( # Show signup banner if user is not logged in SignupBanner( @@ -278,4 +316,6 @@ class EpisodeDetailPage(Component[AnyChildren, EpisodeDetailPageAttrs]): user=user, current_page="", error=None, + page_title=page_title, + meta_tags=meta_tags, ) diff --git a/Biz/PodcastItLater/UI.py b/Biz/PodcastItLater/UI.py index 8959d4e..57d0f33 100644 --- a/Biz/PodcastItLater/UI.py +++ b/Biz/PodcastItLater/UI.py @@ -143,6 +143,8 @@ class PageLayoutAttrs(Attrs): user: dict[str, typing.Any] | None current_page: str error: str | None + page_title: str | None + meta_tags: list[html.meta] | None class PageLayout(Component[AnyChildren, PageLayoutAttrs]): @@ -289,6 +291,8 @@ class PageLayout(Component[AnyChildren, PageLayoutAttrs]): user = self.attrs.get("user") current_page = self.attrs.get("current_page", "") error = self.attrs.get("error") + page_title = self.attrs.get("page_title") or "PodcastItLater" + meta_tags = self.attrs.get("meta_tags") or [] return html.html( html.head( @@ -301,7 +305,8 @@ class PageLayout(Component[AnyChildren, PageLayoutAttrs]): name="color-scheme", content="light dark", ), - html.title("PodcastItLater"), + html.title(page_title), + *meta_tags, create_htmx_script(), ), html.body( |
