Semi-OT: Hugo Site theme not served on CloudFlare Pages

Further Update:
It works as expected when building on vercel: use the url of the actual site–including custom domain–and there is no problem with vercel.

So, I’ve answered the question about baseurl–as per docs and the way I had it.

the problem is with CloudFlare and we’ll see what they suggest about the additional header record they stick on the site that changes the mime type of the style sheet. So, I have confirmed that the mime type for the style sheet created by Hugo becomes application/octet-stream when it MUST be text/css. It is possible that this is the result of some bs “safety” feature of cloudflare that detects non-text in the css file. Or it might not like the long name that hugo generates for the output compiled stylesheet which might look to some not well-written filter like binary data. This is certainly the real problem as I’ve confirmed looking at the received object type in 2 browsers. Of course, there is nothing weird about the css Hugo generates except it can be rather long for some themes and minified. But, normal.

Update: here is the browser web panel error message: The stylesheet https://a-view.org/style.main.min.5ea2f07be7e07e221a7112a3095b89d049b96c48b831f16f1015bf2d95d914e5.css was not loaded because its MIME type, “application/octet-stream”, is not “text/css”.

That’s a new one! I never changed anything in the theme. This is hugely bizarre because that string is not in my hugo directories locally or in the repo. So, CloudFlare is doing some bizarro thing at generate time. Phew!

I have had hours of problems getting the site to render properly. Pages are malformed, etc, because no theme is being applied. I’ve seen this before and it has been because the baseurl is not set correctly. You can see it a-view.org

I have tried many, many permutations of base url to no avail this time.

The site is being generated on CloudFlare Pages. I did not have this problem at Render but Render doesn’t clear caches properly and leaves old versions around that get built.

CloudFlare presents a bit of a challenge. The site is built on one of their generated domains: https://a-view-hugo.pages.dev. When you set a custom domain and have a correct cname record (which they enforce for you) then the site will ALSO be available at https://a-view.org.

So, what’s a choosy mother to do? (from the old American ad for Jif peanut butter). We have several choices:
baseURL = “https://a-view-hugo.pages.dev
baseURL = “https://a-view.org
baseURL = “”

None work. Always broken. But, building locally with hugo server always works–it replaces the base url to localhost:1313. At least this shows that the site is otherwise designed properly.

When I switched from Render to Cloudflare I did not initially change the baseurl in my repo–I forgot–so the rest of the hugo site is the same as it was on Render. I then changed the baseurl in config.toml to every choice above. Very time consuming: edit, commit, push, build each time.

It could be that Cloudflare has the same problem as Render by not cleaning the deploy cache they use. Some of these jamstack places seem a bit rough around the edges technically (even though CloudFlare does lots of other stuff…).

the repo is http://github.com/lewisl/a-view-hugo

I assume that even though the site is always available at the private Cloudflare pages url, no one will ever use that so it’s ok if that one renders broken. And I should use baseurl = “https://a-view.org” when I get that to render correctly.

Let me know if there is something obvious to do.

If not, that means it is a caching problem at CloudFlare for which the only thing is to delete the static site and start over. Which is really no big deal, but a pain to do every time something changes.

Many people have pointed out the caching problem to Render, who have done nothing to fix it.

I just posted the problem at CloudFlare–which is the first time so I’m nice in suggesting that they need to look into it.

Hours lost on minor gotchas.

That’s definitely a topic to ask at the Cloudflare forum. You need to set the content type via headers on Cloudflare pages. They call that page rules.

And regarding baseURL: I would always use the public domain name, not the subdomain name. If you have your own domain.

And “always broken” does not tell us if the site won’t work or if you get the octed-stream error. Again, if a stylesheet is not served as stylesheet then your browser blocks it because an octed stream can on certain OSses wreak havoc if the wrong person clicks the yes/no buttons.

Sometimes a dash at the end of the baseURL is missing and everything suddenly works fine.

But as I wrote: cloudflare forum should know more about the headers.

Also: Your site works fine now when I load it.

Hi @lewisl,

Your dev site, https://a-view-hugo.pages.dev/ is trying to load a stylesheet, directly from your primary site https://a-view.org/, that doesn’t exist: https://a-view.org/style.main.min.5ea2f07be7e07e221a7112a3095b89d049b96c48b831f16f1015bf2d95d914e5.css that’s the only issue.

My guess is that Cloudflare cached your original page, you made some changes to the css (on your primary site) but because nothing changed on the Cloudflare cached site it continues to serve the cached html page which now points to a non-existent resource.

It works now because I am using vercel to deploy it.

  • Lewis

It’s trickier than that. I am using a custom domain. So, the custom domain is substituted into top level resource paths. From the dev url, it doesn’t find the resources. From the custom domain at a-view.org it works except for the bad mime type and the error is different.

Could be a caching problem but the real problem is that CloudFlare’s poorly designed safety filters can’t properly parse a file name. They see the middle of the name as a long string of random characters and guess that it must be binary data and set the mime type to octet-blah (I forget) instead of text/css.

There seem to be 3 solutions:

It works now because I deploy it from vercel and changed my cname record in DNS.

Always broken means the stylesheet is not loaded by the browser and so the rendering is all junky because there is effectively no theme being used. Just one continuous scroll of miss-sized and misplaced stuff: what you’d expect with no theme (because no css).

No styles, because 404: file not found.

That file you link to in your <head> does not exist, follow it and see: <link rel="stylesheet" href="https://a-view.org/style.main.min.5ea2f07be7e07e221a7112a3095b89d049b96c48b831f16f1015bf2d95d914e5.css">

We need to see your repository to know what is going on here. It’s possible that you “double optimize” where you use some hugo minification and then your server optimizes again, thus invalidating the hashes on your stylesheet file name.

Without repo we don’t know.

Sorry, what you are looking at is a bit out of date.

If you go to a-view.org, you will see that it all works because I have it deployed on vercel.

If deploying on CloudFlare, the browser can’t find the resource because of the bad mime type. The offending CSS (the only one because hugo merges all the SASS and CSS into one…) won’t be loaded so the site misrenders (or it renders correctly for a site with no css).

The dev site from CloudFlare Pages is at a-view-org.page.dev. The dev site from vercel is generated from the sha of the commit that the hugo content is sourced to. They use their internal DNS to map from the custom domain name to the latest production deploy. So, if you do this before I push again you can access the dev site (maybe—when I do this when I am logged in, they take me to my “project page”). Anyway, try: https://vercel.com/lewisl1/a-view-hugo/FgvTMFcrGvnxFwMgbbdikz9bxzGM It might not work if you can’t access the project behind the login wall. The good news is that it renders properly because: 1) they don’t mess with the header records; 2) they use the custom domain in the baseURL, and linked to the project through their ui, for what they generate.

Vercel is very quick and they have a somewhat obstructionist “prettified” ui, but impose an elaborate workflow that goes from test to production and maintains a history of all deployments. I suppose for something more complicated with multiple contributors it may be useful but they make all projects use it.

I really do think this is a CloudFlare problem.

Do page rules work for content deployed on the beta service called CloudFlare Pages? I’ll give it a try later. It should work on anything associated with the domain at CloudFlare DNS.

Could be. I think CloudFlare does their own grotli process. I used hugo –gc –minify as my build command. Perhaps hugo by itself…

Here you go: https://github.com/lewisl/a-view-hugo

Note that this build was done from branch new-content. Now, all branches point to the same head…

Thank you. You guys are great.

I understand CI/CD deployment piplines, and caching. In fact, I even looked through your recent deployments: https://github.com/lewisl/a-view-hugo/deployments.

Bottom line though is that the css your broken site links to is not where the html says it is. There is no file to load. The hash in file path does not match the hash in your generated css file. Caching or not, broken links don’t work.

Thanks for being attentive. It does work now when deployed from vercel. I did nothing but change the baseurl and the target build directory. So, it is not what you are saying. I know you know more than me (a low bar to be sure), but that it now works is proof of the pudding.

I can show you the error messages in the browser that show the bad mime type. But, CloudFlare is slowly getting on it and I can send it to their dev discord. Another CloudFlare user confirmed the problem and suggested custom page rules as a work around.

I have not read this entire thread, but I read somewhere that Cloudflare Pages comes with a rather old Hugo version by default, which I assume you can configure.

Yes, very old indeed: 0.54.0! Hah!

Easy to configure although they still don’t have latest available. Set an environment variable:

HUGO_VERSION= 0.80.0

I think they may also have 0.81.0. I did have a layout break on another site with 0.54.0 and worked with 0.80.0.

Double optimization was a good hunch.

So, I posed it on Discord/CloudFlare/Pages (really good activity; smart folks; good suggestions). They said that CloudFlare doesn’t do it’s own optimization. I need to look again because I thought I saw something in their docs that said they did brotli. In any case, my build command is simply “hugo” and I don’t have minify if config.toml. So, it’s not Hugo doing it.

To wrap up. Double optimization was a good hunch, but not the solution.

CloudFlare have a bug in the way Pages generates header records. Who knows if they will fix it.

@Davidsneighbor was on the right path earlier with the pointer to CloudFlare Page Rules.

but, the path had another twist. Rather than Page Rules, which I don’t think works with the “Pages” beta product I was told to create a “Worker”. BTW, you can sort of forget about CloudFlare support. Tier 1 can do some DNS stuff but that is it. I went on Discord/CloudFlare Workers where there are folks who know about Pages (there is a #Pages tag…). They picked it up from my post in the CloudFlare forum and had already posted in Discord. I replied to Joe’s post and he dashed off the JS script needed. Incredibly helpful and quick.

The work around is a bit of a heavy lift: You need a local Node tool that provides a local cli called Wrangler for creating Workers (brew install npm; npm to install wrangler; some bootstrapping with Wrangler–not unlike using Hugo to build skeletons). Each Worker has a small config file and an index.js that runs each time a given route is requested. This JS code resets the bogus type of the css from “application/octet-stream” (arbitrary binary data) to “text/css”–but just making sure that any file that ends in .css gets “text/css”.

What’s interesting is that one of my Hugo sites on CloudFlare worked without this “work around”. I’ll go look but I think the CSS filename must have looked innocent to CloudFlare’s security filters while the other css had a named that tricked them.

I would have said that CloudFlare was ok but for this problem. I have tried Render, Netlify and Vercel. I am sure that all have their fans. This new thing of hosting SSG’s is pretty commoditized though each tries to add their own special icing decorations (YMMV).

I found Render to be pretty good. Not quite as fast as Vercel but close. Vercel wants to give you are multilayered workflow in a pretty UI that seemed to mostly get in the way. Render’s only problem is that you’ll have to integrate it with github manually, which they don’t document correctly. The others do that for you, only requesting you to complete a popup github authorization. Once Render is integrated with github, it is actually pretty nice. The setup and management of build/deploy has lots of options, most of which can be ignored unless you need them. They have the essentials covered and it’s quite easy. And they make it very easy to force re-deploy as sometimes they get a little slow at automatically redeploying after a push (especially if you are hacking around like me with a lot of pushes in quick succession). On a more steady diet of pushes, it seems immediate.

I have a few more sites to create. Each time I’ll give CloudFlare a try. If they have this css problem, I just have to add more routes. If that hangs me up, there is always Render.com or others.

Brotli does not change the content, it just compresses the file for faster transfer from server to browser. The browser should then uncompress it locally and the hash should stay the same.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.