diff --git a/alembic/versions/p6n4k0l2m3_add_oauth_codes_table.py b/alembic/versions/p6n4k0l2m3_add_oauth_codes_table.py
new file mode 100644
index 0000000..d74a687
--- /dev/null
+++ b/alembic/versions/p6n4k0l2m3_add_oauth_codes_table.py
@@ -0,0 +1,37 @@
+"""Add oauth_codes table
+
+Revision ID: p6n4k0l2m3
+Revises: o5m3j9k1l2
+Create Date: 2026-02-23
+"""
+from alembic import op
+import sqlalchemy as sa
+
+revision = "p6n4k0l2m3"
+down_revision = "o5m3j9k1l2"
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ op.create_table(
+ "oauth_codes",
+ sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
+ sa.Column("code", sa.String(128), nullable=False),
+ sa.Column("user_id", sa.Integer(), nullable=False),
+ sa.Column("client_id", sa.String(64), nullable=False),
+ sa.Column("redirect_uri", sa.String(512), nullable=False),
+ sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("used_at", sa.DateTime(timezone=True), nullable=True),
+ sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
+ sa.PrimaryKeyConstraint("id"),
+ sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
+ )
+ op.create_index("ix_oauth_code_code", "oauth_codes", ["code"], unique=True)
+ op.create_index("ix_oauth_code_user", "oauth_codes", ["user_id"])
+
+
+def downgrade() -> None:
+ op.drop_index("ix_oauth_code_user", table_name="oauth_codes")
+ op.drop_index("ix_oauth_code_code", table_name="oauth_codes")
+ op.drop_table("oauth_codes")
diff --git a/browser/templates/_types/auth/_nav.html b/browser/templates/_types/auth/_nav.html
index 9d8042a..93499a8 100644
--- a/browser/templates/_types/auth/_nav.html
+++ b/browser/templates/_types/auth/_nav.html
@@ -1,5 +1,5 @@
{% import 'macros/links.html' as links %}
-{% call links.link(federation_url('/auth/newsletters/'), hx_select_search, select_colours, True, aclass=styles.nav_button) %}
+{% call links.link(account_url('/newsletters/'), hx_select_search, select_colours, True, aclass=styles.nav_button) %}
newsletters
{% endcall %}
{% for link in account_nav_links %}
diff --git a/browser/templates/_types/auth/_newsletter_toggle.html b/browser/templates/_types/auth/_newsletter_toggle.html
index af3a4e1..8bb3f69 100644
--- a/browser/templates/_types/auth/_newsletter_toggle.html
+++ b/browser/templates/_types/auth/_newsletter_toggle.html
@@ -1,6 +1,6 @@