diff --git a/files/templates/default.html b/files/templates/default.html
index f2797dd34..c89290c75 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 6df266f1b..89e9fe6b9 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 65849feb8..4eefd01c2 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 3db71bd8d..505e8d2c0 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 72e1c04f2..df63b7b7b 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 0d130b7fa..d64d9e987 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}}
@@ -71,14 +70,13 @@
{% if p.edited_utc %}{% endif %}
-{% if p.author %}{% endif %}
{% if p.url and p.is_video %}
{% endif %}
-
+
diff --git a/files/templates/submit.html b/files/templates/submit.html
index 4f60e1aa3..fed3caec6 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 6c2dfac90..4d4174d03 100644
--- a/files/templates/userpage.html
+++ b/files/templates/userpage.html
@@ -10,21 +10,20 @@
{% endif %}
{{u.username}}'s profile - {{SITE_TITLE}}
+
-
-
-
+
-
+
-
+
{% endblock %}
diff --git a/files/tests/test_opengraph.py b/files/tests/test_opengraph.py
new file mode 100644
index 000000000..5d333b3bf
--- /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