CORS headers not set for HTML on Flask + Render.com (Cloudflare proxy?), JS/CSS working fine

I’m running into a CORS issue I just can’t solve.

Setup:

  • Backend: Flask app (with Flask-CORS)
  • Hosted: on Render.com
  • Static files: Served via Flask (send_from_directory)
  • Public frontend: solixa.ai
  • Static files domain: custom-va-template.onrender.com
  • I do not have my own Cloudflare account; all proxy/CDN is managed by Render.

What works

  • All JS and CSS files (e.g. /main.js, /styles.css) are loaded cross-origin without CORS errors.
    • I see no CORS error for JS/CSS, and in the network tab I see those requests (from https://solixa.ai to https://custom-va-template.onrender.com) get 200 OK.
  • Only the main HTML file (/index.html) gives a CORS error in the browser.

What fails

  • Whenever my frontend tries to fetch /index.html cross-origin (via fetch, or in devtools), I get:
Access to fetch at 'https://custom-va-template.onrender.com/index.html?v=TIMESTAMP' from origin 'https://solixa.ai' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • Curl test:
curl -i -H "Origin: https://solixa.ai" "https://custom-va-template.onrender.com/index.html"

…shows no Access-Control-Allow-Origin header for HTML.
(But curl to /main.js or /styles.css DOES show the header.)

My Flask config

from flask import Flask, send_from_directory, request, make_response
from flask_cors import CORS
import os

app = Flask(__name__)

ALLOWED_ORIGINS = [
    "https://solixa.ai",
    "https://custom-va-template.onrender.com",
    "http://localhost:8080",
]

CORS(
    app,
    resources={r"/*": {"origins": "*"}},
    supports_credentials=False,
    send_wildcard=True,
    always_send=True,
    automatic_options=True,
)

UI_ASSETS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'frontend')

@app.route('/', methods=['GET', 'HEAD', 'OPTIONS'])
def serve_chatbot_index_html():
    # ... see code above for full details ...
    return send_from_directory(UI_ASSETS_DIR, 'index.html')

I also tried explicit CORS headers, after_request hooks, etc. Nothing works for HTML – but JS/CSS always works.

What I tried

  • Various Flask-CORS configs, always with origins set, also wildcards.
  • Explicit @app.after_request adding ACAO headers, setting Cache-Control: no-store for HTML.
  • Purging Cloudflare cache, clearing Render cache, redeploys, versioned query strings (cache busters).
  • All CDN headers (Vary, Origin, etc) double checked.
  • No effect: HTML never gets ACAO in response.

Questions

  • Why would Render/Cloudflare serve CORS headers for JS/CSS but NOT for HTML, even with identical Flask/CORS config?
  • Can Cloudflare or Render be stripping or altering the headers just for HTML content types?
  • How can I ensure my HTML (index.html) always gets the right Access-Control-Allow-Origin header cross-origin, as my JS/CSS already do?
  • What else can I try on the Flask or Render side? Is this a known Render+Cloudflare issue?

Any help is very appreciated!