From c3c2739acaf9c2db97ddc8f91f9706dd41d0bfdb Mon Sep 17 00:00:00 2001 From: Stephen Hayes Date: Thu, 26 Feb 2026 12:39:26 -0600 Subject: [PATCH 1/3] Fix OpenGraph tags on all important pages (#130) - Make og:image URLs absolute by prepending SITE_FULL (social crawlers need full URLs, not relative /assets/ paths) - Fix og:type: use "website" for general pages, "article" for posts, "profile" for user pages - Fix og:site_name: use SITE_TITLE consistently instead of request.host - Remove duplicate og:site_name tags in default.html, settings.html, settings2.html - Fix og:url in settings.html (was missing scheme, just had hostname) - Fix twitter:url for comment permalinks (was pointing to post instead of comment) - Add OG + Twitter Card tags to error pages, submit page, and login forms which previously had none - Remove non-standard og:author tags (use og:article:author instead) - Make og:title on userpage include site name for better social previews Co-Authored-By: Claude Opus 4.6 --- files/templates/default.html | 11 ++++------- files/templates/errors/error.html | 15 ++++++++++++++- files/templates/login/authforms.html | 14 ++++++++++++++ files/templates/settings.html | 19 ++++++++----------- files/templates/settings2.html | 11 ++++------- files/templates/submission.html | 7 +++---- files/templates/submit.html | 12 ++++++++++++ files/templates/userpage.html | 9 ++++----- 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/files/templates/default.html b/files/templates/default.html index f2797dd343..c89290c75e 100644 --- a/files/templates/default.html +++ b/files/templates/default.html @@ -41,21 +41,18 @@ {% block title %} {{SITE_TITLE}} - + - - + + - - - - + {% endblock %} diff --git a/files/templates/errors/error.html b/files/templates/errors/error.html index 6df266f1b6..89e9fe6b92 100644 --- a/files/templates/errors/error.html +++ b/files/templates/errors/error.html @@ -1,6 +1,19 @@ {% extends "default.html" %} {% block title %} -{{code}} {{error}} +{{code}} {{error}} - {{SITE_TITLE}} + + + + + + + + + + + + + {% endblock %} {% block pagetype %}error-{{code}}{% endblock %} {% block content %} diff --git a/files/templates/login/authforms.html b/files/templates/login/authforms.html index 65849feb85..4eefd01c29 100644 --- a/files/templates/login/authforms.html +++ b/files/templates/login/authforms.html @@ -6,6 +6,20 @@ {% block pagetitle %}{{SITE_TITLE}}{% endblock %} + + + + + + + + + + + + + + {% if v %} diff --git a/files/templates/settings.html b/files/templates/settings.html index 3db71bd8dc..505e8d2c0a 100644 --- a/files/templates/settings.html +++ b/files/templates/settings.html @@ -13,22 +13,19 @@ {% block pagetitle %}Settings - {{SITE_TITLE}}{% endblock %} - - - - - + + + + + - - - - + - - + + diff --git a/files/templates/settings2.html b/files/templates/settings2.html index 72e1c04f21..df63b7b7b0 100644 --- a/files/templates/settings2.html +++ b/files/templates/settings2.html @@ -16,21 +16,18 @@ - + - - + + - - - - + diff --git a/files/templates/submission.html b/files/templates/submission.html index 0d130b7fa1..e06cf07ad6 100644 --- a/files/templates/submission.html +++ b/files/templates/submission.html @@ -46,14 +46,13 @@ {% if comment_info.edited_utc %}{% endif %} - {% if p.is_video %} {% endif %} - + @@ -61,7 +60,7 @@ - + {% else %} {{p.plaintitle(v)}} - {{SITE_TITLE}} @@ -78,7 +77,7 @@ {% endif %} - + diff --git a/files/templates/submit.html b/files/templates/submit.html index 4f60e1aa38..fed3caec6a 100644 --- a/files/templates/submit.html +++ b/files/templates/submit.html @@ -11,6 +11,18 @@ {% block title %} Create a post - {{SITE_TITLE}} + + + + + + + + + + + + {% endblock %} diff --git a/files/templates/userpage.html b/files/templates/userpage.html index 6c2dfac908..4d4174d035 100644 --- a/files/templates/userpage.html +++ b/files/templates/userpage.html @@ -10,21 +10,20 @@ {% endif %} {{u.username}}'s profile - {{SITE_TITLE}} + - - - + - + - + {% endblock %} From f9d48035491ea2043f7af280d730291ea34b8407 Mon Sep 17 00:00:00 2001 From: Stephen Hayes Date: Thu, 26 Feb 2026 22:41:28 -0600 Subject: [PATCH 2/3] test: add OpenGraph meta tag tests Adds test_opengraph.py verifying: - Front page has og:title, og:image, og:type=website, twitter tags - og:site_name appears exactly once (no duplicates) - og:author is not present on non-article pages - Post pages have og:title, og:image, og:type=article - Login page has OG tags - User profile has og:type=profile Co-Authored-By: Claude Opus 4.6 --- files/tests/test_opengraph.py | 127 ++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 files/tests/test_opengraph.py diff --git a/files/tests/test_opengraph.py b/files/tests/test_opengraph.py new file mode 100644 index 0000000000..5d333b3bf0 --- /dev/null +++ b/files/tests/test_opengraph.py @@ -0,0 +1,127 @@ +"""Tests for OpenGraph meta tags (#130). + +Verifies that key pages include proper og:title, og:image, and og:site_name +meta tags, and that image URLs are absolute (prefixed with SITE_FULL). +""" +from . import util_accounts +from . import util_submissions + + +def test_front_page_has_og_title(): + """Test that the front page includes og:title meta tag""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + assert 'og:title' in response.text + + +def test_front_page_has_og_image(): + """Test that the front page includes og:image meta tag""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + assert 'og:image' in response.text + + +def test_front_page_og_type_is_website(): + """Test that the front page uses og:type website (not article)""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + assert 'og:type' in response.text + # Should be "website" not "article" for the homepage + assert 'content="website"' in response.text + + +def test_front_page_og_site_name_not_request_host(): + """Test that og:site_name uses SITE_TITLE, not request.host""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + # Should not use request.host (which would be 'localhost' in tests) + assert 'og:site_name' in response.text + # og:site_name should appear exactly once (no duplicates) + assert response.text.count('og:site_name') == 1 + + +def test_front_page_has_twitter_tags(): + """Test that the front page includes Twitter card meta tags""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + assert 'twitter:card' in response.text + assert 'twitter:title' in response.text + assert 'twitter:image' in response.text + + +def test_post_page_has_og_title(): + """Test that a post page includes og:title meta tag""" + client, user = util_accounts.create_test_client_and_user() + post = util_submissions.create_submission_for_client(client) + + response = client.get(f"/post/{post.id}") + assert response.status_code == 200 + assert 'og:title' in response.text + + +def test_post_page_has_og_image(): + """Test that a post page includes og:image meta tag""" + client, user = util_accounts.create_test_client_and_user() + post = util_submissions.create_submission_for_client(client) + + response = client.get(f"/post/{post.id}") + assert response.status_code == 200 + assert 'og:image' in response.text + + +def test_post_page_og_type_is_article(): + """Test that a post page uses og:type article""" + client, user = util_accounts.create_test_client_and_user() + post = util_submissions.create_submission_for_client(client) + + response = client.get(f"/post/{post.id}") + assert response.status_code == 200 + assert 'content="article"' in response.text + + +def test_login_page_has_og_tags(): + """Test that the login page includes OG meta tags""" + client = util_accounts.create_logged_off_client() + + response = client.get("/login") + assert response.status_code == 200 + assert 'og:title' in response.text + assert 'og:image' in response.text + + +def test_user_profile_has_og_tags(): + """Test that a user profile page includes OG meta tags""" + client, user = util_accounts.create_test_client_and_user() + + response = client.get(f"/@{user.username}") + assert response.status_code == 200 + assert 'og:title' in response.text + assert 'og:image' in response.text + + +def test_user_profile_og_type_is_profile(): + """Test that a user profile page uses og:type profile""" + client, user = util_accounts.create_test_client_and_user() + + response = client.get(f"/@{user.username}") + assert response.status_code == 200 + assert 'content="profile"' in response.text + + +def test_no_og_author_on_non_article_pages(): + """Test that og:author is not present on pages that are not articles""" + client = util_accounts.create_logged_off_client() + + response = client.get("/") + assert response.status_code == 200 + assert 'og:author' not in response.text From acbc55acb8f3898f642fa62587fdd70bade51d63 Mon Sep 17 00:00:00 2001 From: Stephen Hayes Date: Fri, 27 Feb 2026 12:01:23 -0600 Subject: [PATCH 3/3] fix: remove redundant og:author meta tag (og:article:author already present) Co-Authored-By: Claude Opus 4.6 --- files/templates/submission.html | 1 - 1 file changed, 1 deletion(-) diff --git a/files/templates/submission.html b/files/templates/submission.html index e06cf07ad6..d64d9e9875 100644 --- a/files/templates/submission.html +++ b/files/templates/submission.html @@ -70,7 +70,6 @@ {% if p.edited_utc %}{% endif %} -{% if p.author %}{% endif %} {% if p.url and p.is_video %}