Enable cross-subdomain htmx and purify layout to sexp
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m15s

- Disable htmx selfRequestsOnly, add CORS headers for *.rose-ash.com
- Remove same-origin guards from ~menu-row and ~nav-link htmx attrs
- Convert ~app-layout from string-concatenated HTML to pure sexp tree
- Extract ~app-head component, replace ~app-shell with inline structure
- Convert hamburger SVG from Python HTML constant to ~hamburger sexp component
- Fix cross-domain fragment URLs (events_url, market_url)
- Fix starts-with? primitive to handle nil values
- Fix duplicate admin menu rows on OOB swaps
- Add calendar admin nav links (slots, description)
- Convert slots page from Jinja to sexp rendering
- Disable page caching in development mode
- Backfill migration to clean orphaned container_relations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 12:09:00 +00:00
parent d2f1da4944
commit eda95ec58b
14 changed files with 251 additions and 160 deletions

View File

@@ -102,6 +102,10 @@ def create_base_app(
# Cache app prefix for key namespacing
app.config["CACHE_APP_PREFIX"] = name
# Disable page caching in development
env = os.getenv("ENVIRONMENT", "development")
app.config["NO_PAGE_CACHE"] = env not in ("production", "staging")
# --- infrastructure ---
register_middleware(app)
register_db(app)
@@ -276,6 +280,15 @@ def create_base_app(
response.delete_cookie("blog_session", domain=".rose-ash.com", path="/")
return response
@app.after_request
async def _cors_for_subdomains(response):
origin = request.headers.get("Origin", "")
if origin.endswith(".rose-ash.com") or origin.endswith(".localhost"):
response.headers["Access-Control-Allow-Origin"] = origin
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Allow-Headers"] = "HX-Request, HX-Target, HX-Current-URL, HX-Trigger, HX-Boosted, Content-Type"
return response
@app.after_request
async def _add_hx_preserve_search_header(response):
value = request.headers.get("X-Search")