Rename coop to blog throughout codebase

- coop_url() → blog_url(), AUTH_APP default → "blog"
- Session cookie: coop_session → blog_session
- Config keys: coop_root/coop_title → market_root/market_title
- All Jinja templates: coop_url → blog_url, coop_title → market_title
- Template blocks: coop-child-header → blog-child-header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-23 08:32:46 +00:00
parent cc22b21b18
commit 798087de9a
27 changed files with 35 additions and 35 deletions

View File

@@ -1,9 +1,9 @@
# The monolith has been split into three apps (apps/coop, apps/market, apps/cart). # The monolith has been split into three apps (apps/blog, apps/market, apps/cart).
# This package remains for shared infrastructure modules (middleware, redis_cacher, # This package remains for shared infrastructure modules (middleware, redis_cacher,
# csrf, errors, authz, filters, utils, bp/*). # csrf, errors, authz, filters, utils, bp/*).
# #
# To run individual apps: # To run individual apps:
# hypercorn apps.coop.app:app --bind 0.0.0.0:8000 # hypercorn apps.blog.app:app --bind 0.0.0.0:8000
# hypercorn apps.market.app:app --bind 0.0.0.0:8001 # hypercorn apps.market.app:app --bind 0.0.0.0:8001
# hypercorn apps.cart.app:app --bind 0.0.0.0:8002 # hypercorn apps.cart.app:app --bind 0.0.0.0:8002
# #

View File

@@ -18,7 +18,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
<form action="{{ coop_url('/auth/logout/') }}" method="post"> <form action="{{ blog_url('/auth/logout/') }}" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button <button
type="submit" type="submit"

View File

@@ -1,5 +1,5 @@
{% import 'macros/links.html' as links %} {% import 'macros/links.html' as links %}
{% call links.link(coop_url('/auth/newsletters/'), hx_select_search, select_colours, True, aclass=styles.nav_button) %} {% call links.link(blog_url('/auth/newsletters/'), hx_select_search, select_colours, True, aclass=styles.nav_button) %}
newsletters newsletters
{% endcall %} {% endcall %}
{% for link in account_nav_links %} {% for link in account_nav_links %}

View File

@@ -1,6 +1,6 @@
<div id="nl-{{ un.newsletter_id }}" class="flex items-center"> <div id="nl-{{ un.newsletter_id }}" class="flex items-center">
<button <button
hx-post="{{ coop_url('/auth/newsletter/' ~ un.newsletter_id ~ '/toggle/') }}" hx-post="{{ blog_url('/auth/newsletter/' ~ un.newsletter_id ~ '/toggle/') }}"
hx-headers='{"X-CSRFToken": "{{ csrf_token() }}"}' hx-headers='{"X-CSRFToken": "{{ csrf_token() }}"}'
hx-target="#nl-{{ un.newsletter_id }}" hx-target="#nl-{{ un.newsletter_id }}"
hx-swap="outerHTML" hx-swap="outerHTML"

View File

@@ -22,7 +22,7 @@
{# No subscription row yet — show an off toggle that will create one #} {# No subscription row yet — show an off toggle that will create one #}
<div id="nl-{{ item.newsletter.id }}" class="flex items-center"> <div id="nl-{{ item.newsletter.id }}" class="flex items-center">
<button <button
hx-post="{{ coop_url('/auth/newsletter/' ~ item.newsletter.id ~ '/toggle/') }}" hx-post="{{ blog_url('/auth/newsletter/' ~ item.newsletter.id ~ '/toggle/') }}"
hx-headers='{"X-CSRFToken": "{{ csrf_token() }}"}' hx-headers='{"X-CSRFToken": "{{ csrf_token() }}"}'
hx-target="#nl-{{ item.newsletter.id }}" hx-target="#nl-{{ item.newsletter.id }}"
hx-swap="outerHTML" hx-swap="outerHTML"

View File

@@ -22,7 +22,7 @@
<p class="mt-6 text-sm"> <p class="mt-6 text-sm">
<a <a
href="{{ coop_url('/auth/login/') }}" href="{{ blog_url('/auth/login/') }}"
class="text-stone-600 dark:text-stone-300 hover:underline" class="text-stone-600 dark:text-stone-300 hover:underline"
> >
← Back ← Back

View File

@@ -1,7 +1,7 @@
{% import 'macros/links.html' as links %} {% import 'macros/links.html' as links %}
{% macro header_row(oob=False) %} {% macro header_row(oob=False) %}
{% call links.menu_row(id='auth-row', oob=oob) %} {% call links.menu_row(id='auth-row', oob=oob) %}
{% call links.link(coop_url('/auth/account/'), hx_select_search ) %} {% call links.link(blog_url('/auth/account/'), hx_select_search ) %}
<i class="fa-solid fa-user"></i> <i class="fa-solid fa-user"></i>
<div>account</div> <div>account</div>
{% endcall %} {% endcall %}

View File

@@ -14,7 +14,7 @@
{% endif %} {% endif %}
<form <form
method="post" action="{{ coop_url('/auth/start/') }}" method="post" action="{{ blog_url('/auth/start/') }}"
class="mt-6 space-y-5" class="mt-6 space-y-5"
> >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">

View File

@@ -17,7 +17,7 @@
{% if _count == 0 %} {% if _count == 0 %}
<div class="h-12 w-12 rounded-full overflow-hidden border border-stone-300 flex-shrink-0"> <div class="h-12 w-12 rounded-full overflow-hidden border border-stone-300 flex-shrink-0">
<a <a
href="{{ coop_url('/') }}" href="{{ blog_url('/') }}"
class="h-full w-full font-bold text-5xl flex-shrink-0 flex flex-row items-center gap-1" class="h-full w-full font-bold text-5xl flex-shrink-0 flex flex-row items-center gap-1"
> >
<img <img

View File

@@ -6,7 +6,7 @@
{% from 'macros/scrolling_menu.html' import scrolling_menu with context %} {% from 'macros/scrolling_menu.html' import scrolling_menu with context %}
{% call(entry_post) scrolling_menu('entry-posts-container', entry_posts) %} {% call(entry_post) scrolling_menu('entry-posts-container', entry_posts) %}
<a <a
href="{{ coop_url('/' + entry_post.slug + '/') }}" href="{{ blog_url('/' + entry_post.slug + '/') }}"
class="flex items-center gap-2 px-3 py-2 hover:bg-stone-100 rounded transition text-sm border sm:whitespace-nowrap sm:flex-shrink-0"> class="flex items-center gap-2 px-3 py-2 hover:bg-stone-100 rounded transition text-sm border sm:whitespace-nowrap sm:flex-shrink-0">
{% if entry_post.feature_image %} {% if entry_post.feature_image %}
<img src="{{ entry_post.feature_image }}" <img src="{{ entry_post.feature_image }}"

View File

@@ -9,7 +9,7 @@
{% from 'macros/scrolling_menu.html' import scrolling_menu with context %} {% from 'macros/scrolling_menu.html' import scrolling_menu with context %}
{% call(entry_post) scrolling_menu('entry-posts-container', entry_posts) %} {% call(entry_post) scrolling_menu('entry-posts-container', entry_posts) %}
<a <a
href="{{ coop_url('/' + entry_post.slug + '/') }}" href="{{ blog_url('/' + entry_post.slug + '/') }}"
class="{{styles.nav_button}}" class="{{styles.nav_button}}"
> >
{% if entry_post.feature_image %} {% if entry_post.feature_image %}

View File

@@ -2,7 +2,7 @@
class="font-bold text-xl flex-shrink-0 flex gap-2 items-center"> class="font-bold text-xl flex-shrink-0 flex gap-2 items-center">
<div> <div>
<i class="fa fa-shop"></i> <i class="fa fa-shop"></i>
{{ coop_title }} {{ market_title }}
</div> </div>
<div class="flex flex-col md:flex-row md:gap-2 text-xs"> <div class="flex flex-col md:flex-row md:gap-2 text-xs">
<div> <div>

View File

@@ -5,7 +5,7 @@
hx-swap-oob="outerHTML"> hx-swap-oob="outerHTML">
{% from 'macros/scrolling_menu.html' import scrolling_menu with context %} {% from 'macros/scrolling_menu.html' import scrolling_menu with context %}
{% call(item) scrolling_menu('menu-items-container', menu_items) %} {% call(item) scrolling_menu('menu-items-container', menu_items) %}
{% set _href = _app_slugs.get(item.slug, coop_url('/' + item.slug + '/')) %} {% set _href = _app_slugs.get(item.slug, blog_url('/' + item.slug + '/')) %}
<a <a
href="{{ _href }}" href="{{ _href }}"
{% if item.slug not in _app_slugs %} {% if item.slug not in _app_slugs %}

View File

@@ -1,7 +1,7 @@
{% import 'macros/links.html' as links %} {% import 'macros/links.html' as links %}
{% macro header_row(oob=False) %} {% macro header_row(oob=False) %}
{% call links.menu_row(id='post-row', oob=oob) %} {% call links.menu_row(id='post-row', oob=oob) %}
<a href="{{ coop_url('/' + post.slug + '/') }}" class="flex items-center gap-2 px-3 py-2 rounded whitespace-normal text-center break-words leading-snug"> <a href="{{ blog_url('/' + post.slug + '/') }}" class="flex items-center gap-2 px-3 py-2 rounded whitespace-normal text-center break-words leading-snug">
{% if post.feature_image %} {% if post.feature_image %}
<img <img
src="{{ post.feature_image }}" src="{{ post.feature_image }}"

View File

@@ -30,7 +30,7 @@
{% block filter %} {% block filter %}
{% call layout.details() %} {% call layout.details() %}
{% call layout.summary('coop-child-header') %} {% call layout.summary('blog-child-header') %}
{% endcall %} {% endcall %}
{% call layout.menu('blog-child-menu') %} {% call layout.menu('blog-child-menu') %}
{% endcall %} {% endcall %}

View File

@@ -30,8 +30,8 @@
{% block filter %} {% block filter %}
{% call layout.details() %} {% call layout.details() %}
{% call layout.summary('coop-child-header') %} {% call layout.summary('blog-child-header') %}
{% block coop_child_summary %} {% block blog_child_summary %}
{% endblock %} {% endblock %}
{% endcall %} {% endcall %}
{% call layout.menu('blog-child-menu') %} {% call layout.menu('blog-child-menu') %}

View File

@@ -1,5 +1,5 @@
{% set href=coop_url('/auth/account/') %} {% set href=blog_url('/auth/account/') %}
<a <a
href="{{ href }}" href="{{ href }}"
class="justify-center cursor-pointer flex flex-row items-center p-3 gap-2 rounded bg-stone-200 text-black {{select_colours}}" class="justify-center cursor-pointer flex flex-row items-center p-3 gap-2 rounded bg-stone-200 text-black {{select_colours}}"

View File

@@ -4,7 +4,7 @@
id="menu-items-nav-wrapper"> id="menu-items-nav-wrapper">
{% from 'macros/scrolling_menu.html' import scrolling_menu with context %} {% from 'macros/scrolling_menu.html' import scrolling_menu with context %}
{% call(item) scrolling_menu('menu-items-container', menu_items) %} {% call(item) scrolling_menu('menu-items-container', menu_items) %}
{% set _href = _app_slugs.get(item.slug, coop_url('/' + item.slug + '/')) %} {% set _href = _app_slugs.get(item.slug, blog_url('/' + item.slug + '/')) %}
<a <a
href="{{ _href }}" href="{{ _href }}"
aria-selected="{{ 'true' if (item.slug == _first_seg or item.slug == app_name) else 'false' }}" aria-selected="{{ 'true' if (item.slug == _first_seg or item.slug == app_name) else 'false' }}"

View File

@@ -1,6 +1,6 @@
{% import 'macros/links.html' as links %} {% import 'macros/links.html' as links %}
{% if g.rights.admin %} {% if g.rights.admin %}
<a href="{{ coop_url('/settings/') }}" class="{{styles.nav_button}}"> <a href="{{ blog_url('/settings/') }}" class="{{styles.nav_button}}">
<i class="fa fa-cog" aria-hidden="true"></i> <i class="fa fa-cog" aria-hidden="true"></i>
</a> </a>
{% endif %} {% endif %}

View File

@@ -31,7 +31,7 @@
← Go Back ← Go Back
</button> </button>
<a <a
href="{{ coop_url('/') }}" href="{{ blog_url('/') }}"
class="px-4 py-2 bg-stone-800 text-white rounded hover:bg-stone-700 transition-colors text-center" class="px-4 py-2 bg-stone-800 text-white rounded hover:bg-stone-700 transition-colors text-center"
> >
Home Home

View File

@@ -1,5 +1,5 @@
{% set href=coop_url('/auth/account/') %} {% set href=blog_url('/auth/account/') %}
<a <a
href="{{ href }}" href="{{ href }}"
data-close-details data-close-details

View File

@@ -1,6 +1,6 @@
{% macro title(_class='') %} {% macro title(_class='') %}
<a <a
href="{{ coop_url('/') }}" href="{{ blog_url('/') }}"
class="{{_class}}" class="{{_class}}"
> >
<h1> <h1>

View File

@@ -7,7 +7,7 @@ from quart import Quart, g
DATABASE_URL = ( DATABASE_URL = (
os.getenv("DATABASE_URL_ASYNC") os.getenv("DATABASE_URL_ASYNC")
or os.getenv("DATABASE_URL") or os.getenv("DATABASE_URL")
or "postgresql+asyncpg://localhost/coop" or "postgresql+asyncpg://localhost/blog"
) )
_engine = create_async_engine( _engine = create_async_engine(

View File

@@ -54,7 +54,7 @@ def create_base_app(
context_fn: context_fn:
Async function returning a dict for template context. Async function returning a dict for template context.
Each app provides its own — the cart app queries locally, Each app provides its own — the cart app queries locally,
while coop/market apps fetch via internal API. while blog/market apps fetch via internal API.
If not provided, a minimal default context is used. If not provided, a minimal default context is used.
before_request_fns: before_request_fns:
Extra before-request hooks (e.g. cart_loader for the cart app). Extra before-request hooks (e.g. cart_loader for the cart app).
@@ -84,7 +84,7 @@ def create_base_app(
cookie_domain = os.getenv("SESSION_COOKIE_DOMAIN") # e.g. ".rose-ash.com" cookie_domain = os.getenv("SESSION_COOKIE_DOMAIN") # e.g. ".rose-ash.com"
if cookie_domain: if cookie_domain:
app.config["SESSION_COOKIE_DOMAIN"] = cookie_domain app.config["SESSION_COOKIE_DOMAIN"] = cookie_domain
app.config["SESSION_COOKIE_NAME"] = "coop_session" app.config["SESSION_COOKIE_NAME"] = "blog_session"
# Ghost / Redis config # Ghost / Redis config
app.config["GHOST_API_URL"] = os.getenv("GHOST_API_URL") app.config["GHOST_API_URL"] = os.getenv("GHOST_API_URL")

View File

@@ -13,7 +13,7 @@ from shared.browser.app.csrf import generate_csrf_token
from shared.browser.app.authz import has_access from shared.browser.app.authz import has_access
from shared.browser.app.filters import register as register_filters from shared.browser.app.filters import register as register_filters
from .urls import coop_url, market_url, cart_url, events_url, login_url, page_cart_url, market_product_url from .urls import blog_url, market_url, cart_url, events_url, login_url, page_cart_url, market_product_url
def setup_jinja(app: Quart) -> None: def setup_jinja(app: Quart) -> None:
@@ -93,7 +93,7 @@ def setup_jinja(app: Quart) -> None:
app.jinja_env.globals["site"] = site app.jinja_env.globals["site"] = site
# cross-app URL helpers available in all templates # cross-app URL helpers available in all templates
app.jinja_env.globals["coop_url"] = coop_url app.jinja_env.globals["blog_url"] = blog_url
app.jinja_env.globals["market_url"] = market_url app.jinja_env.globals["market_url"] = market_url
app.jinja_env.globals["cart_url"] = cart_url app.jinja_env.globals["cart_url"] = cart_url
app.jinja_env.globals["events_url"] = events_url app.jinja_env.globals["events_url"] = events_url

View File

@@ -21,8 +21,8 @@ def app_url(app_name: str, path: str = "/") -> str:
return base + path return base + path
def coop_url(path: str = "/") -> str: def blog_url(path: str = "/") -> str:
return app_url("coop", path) return app_url("blog", path)
def market_url(path: str = "/") -> str: def market_url(path: str = "/") -> str:
@@ -66,9 +66,9 @@ def market_product_url(product_slug: str, suffix: str = "", market_place=None) -
def login_url(next_url: str = "") -> str: def login_url(next_url: str = "") -> str:
# Auth lives in blog (coop) for now. Set AUTH_APP=federation to switch. # Auth lives in blog for now. Set AUTH_APP=federation to switch.
from quart import session as qsession from quart import session as qsession
auth_app = os.getenv("AUTH_APP", "coop") auth_app = os.getenv("AUTH_APP", "blog")
base = app_url(auth_app, "/auth/login/") base = app_url(auth_app, "/auth/login/")
params: list[str] = [] params: list[str] = []
if next_url: if next_url:

View File

@@ -48,8 +48,8 @@ class _WidgetRegistry:
slug = w.slug slug = w.slug
def _href(s=slug): def _href(s=slug):
from shared.infrastructure.urls import coop_url from shared.infrastructure.urls import blog_url
return coop_url(f"/auth/{s}/") return blog_url(f"/auth/{s}/")
self._account_nav.append(AccountNavLink( self._account_nav.append(AccountNavLink(
label=w.label, label=w.label,