diff --git a/app/__init__.py b/app/__init__.py index 4f1ce4c..60adf42 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -147,6 +147,47 @@ def create_app() -> FastAPI: ) return response + # Coop fragment pre-fetch — inject nav-tree, auth-menu, cart-mini into + # request.state for full-page HTML renders. Skips HTMX, API, and + # internal paths. Failures are silent (fragments default to ""). + _FRAG_SKIP = ("/auth/", "/api/", "/internal/", "/health", "/oembed", + "/ipfs/", "/download/", "/inbox", "/static/") + + @app.middleware("http") + async def coop_fragments_middleware(request: Request, call_next): + path = request.url.path + if ( + request.method != "GET" + or any(path.startswith(p) for p in _FRAG_SKIP) + or request.headers.get("hx-request") + or request.headers.get(fragments.FRAGMENT_HEADER) + ): + request.state.nav_tree_html = "" + request.state.auth_menu_html = "" + request.state.cart_mini_html = "" + return await call_next(request) + + from artdag_common.fragments import fetch_fragments as _fetch_frags + + user = get_user_from_cookie(request) + auth_params = {"email": user.email} if user else {} + nav_params = {"app_name": "artdag", "path": path} + + try: + nav_tree_html, auth_menu_html, cart_mini_html = await _fetch_frags([ + ("blog", "nav-tree", nav_params), + ("account", "auth-menu", auth_params or None), + ("cart", "cart-mini", None), + ]) + except Exception: + nav_tree_html = auth_menu_html = cart_mini_html = "" + + request.state.nav_tree_html = nav_tree_html + request.state.auth_menu_html = auth_menu_html + request.state.cart_mini_html = cart_mini_html + + return await call_next(request) + # Initialize Jinja2 templates template_dir = Path(__file__).parent / "templates" app.state.templates = create_jinja_env(template_dir) diff --git a/app/templates/base.html b/app/templates/base.html index c53ceb4..d659065 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -14,20 +14,36 @@ Art-DAG Media{% if nav_counts and nav_counts.media %} ({{ nav_counts.media }}){% endif %} Storage{% if nav_counts and nav_counts.storage %} ({{ nav_counts.storage }}){% endif %} Client + {% if request and request.state.nav_tree_html %} + | +
+ {{ request.state.nav_tree_html | safe }} +
+ {% else %} | Blog Market Account + {% endif %} {% endblock %} {% block nav_right %} -{% if user %}
+ {% if request and request.state.cart_mini_html %} +
+ {{ request.state.cart_mini_html | safe }} +
+ {% endif %} + {% if request and request.state.auth_menu_html %} +
+ {{ request.state.auth_menu_html | safe }} +
+ {% elif user %} {{ user.username }} Logout + {% else %} + Login + {% endif %}
-{% else %} -Login -{% endif %} {% endblock %} diff --git a/docker-compose.yml b/docker-compose.yml index 9b7b6ca..301e439 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -73,6 +73,10 @@ services: # IPFS_API multiaddr - used for all IPFS operations (add, cat, pin) - IPFS_API=/dns/ipfs/tcp/5001 - CACHE_DIR=/data/cache + # Coop app internal URLs for fragment composition + - INTERNAL_URL_BLOG=http://blog:8000 + - INTERNAL_URL_CART=http://cart:8000 + - INTERNAL_URL_ACCOUNT=http://account:8000 # DATABASE_URL, ADMIN_TOKEN, ARTDAG_CLUSTER_KEY, # L2_SERVER, L2_DOMAIN, IPFS_GATEWAY_URL from .env file healthcheck: