Fixing asset loading issues in Publii websites
Having trouble with broken icons, photos, and other assets not loading correctly on your Publii website? This common issue stems from inconsistent use of website address prefixes (like http:// vs https:// or with/without www) during the deployment configuration in Publii. This tutorial will guide you through the steps to ensure all your website assets load correctly by enforcing a consistent URL structure across your site using techniques like .htaccess redirects and platform-specific configuration for services like Netlify, Google Cloud, and S3.
The Problem
When setting up your Publii deployment server settings, you must provide the website address. Users occasionally enter various versions of the address, for instance:
- http://yourdomain.com
- https://yourdomain.com
- http://www.yourdomain.com
- https://www.yourdomain.com
Later, when visitors access the website using a different URL prefix than the one configured in Publii (for example, visiting https://www.yourdomain.com when the deployment was set with http://yourdomain.com), the paths to the assets generated by Publii become incorrect. This is because the generated HTML includes absolute URLs for assets based on the configured deployment address.
Example Scenario
Let's say you configured your Publii deployment with http://yourdomain.com. Publii will generate asset links like:
<img src="http://yourdomain.com/assets/images/logo.png"></code>If a user visits your website via https://www.yourdomain.com, their browser will attempt to load the image from http://yourdomain.com/assets/images/logo.png. Due to the different protocol and the presence of "www", this request might fail or trigger browser security warnings.
Solutions to Enforce Consistent URLs:
To prevent this, you must ensure that all website traffic consistently uses the same URL prefix (e.g., always using https://www.yourdomain.com). Here are solutions based on different deployment environments:
1. Using .htaccess (for FTP):
If your website is hosted on a traditional Apache server, you can use the .htaccess file to enforce specific URL redirects. Here are some common rules:
Force www and https:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Force non-www and https:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]
Force https only (assuming you have an SSL certificate):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
This rule only redirects HTTP traffic to HTTPS, leaving the "www" prefix as it is.
Important: Place these rules in the .htaccess file located in the root directory of your website on the server.
2. Configuration for Cloud Platforms
While .htaccess is specific to Apache servers, similar redirection logic can be configured on platforms like Netlify, Google Cloud, and S3.
Netlify
Netlify provides a netlify.toml file for configuration, including redirects. You can add rules like:
[[redirects]]
from = "http://yourdomain.com/*"
to = "https://www.yourdomain.com/:splat"
status = 301
force = true
[[redirects]]
from = "http://www.yourdomain.com/*"
to = "https://www.yourdomain.com/:splat"
status = 301
force = true
[[redirects]]
from = "https://yourdomain.com/*"
to = "https://www.yourdomain.com/:splat"
status = 301
force = trueYou can similarly create rules to enforce non-www or only https.
Google Cloud Storage
Google Cloud Storage supports URL redirects for static websites. To configure, enable "Static Website Hosting" in the bucket settings and upload a website-config.json file with redirection rules. For example:
[
{
"condition": {
"httpErrorCodeReturnedEquals": "404",
"keyPrefixEquals": ""
},
"redirect": {
"protocol": "https",
"hostName": "www.yourdomain.com",
"replaceKeyPrefixWith": ""
}
}
]Upload the file using: gsutil web set website-config.json gs://your-bucket-name. Refer to the official documentation for details.
Amazon S3
Amazon S3 allows URL redirects for static websites via bucket properties. Enable "Static Website Hosting" in the bucket settings and define redirect rules. For example, to redirect HTTP to HTTPS or manage www prefixes, configure a routing-rules.json file:
[
{
"Condition": {
"KeyPrefixEquals": ""
},
"Redirect": {
"Protocol": "https",
"HostName": "www.yourdomain.com",
"ReplaceKeyPrefixWith": ""
}
}
]Upload the file through the AWS Management Console or CLI. Refer to the official documentation for details.
GitHub Pages
GitHub Pages doesn't directly support .htaccess-style redirections, but you can still manage redirects for custom domains using DNS settings and specific repository configurations.
Configuration:
- DNS Setup:
Ensure your DNS records are correctly pointing to GitHub Pages. For apex domains, use A records that point to GitHub's IP addresses (listed in GitHub’s documentation). For subdomains (likewww.yourdomain.com), use a CNAME record pointing to your GitHub Pages site (e.g.,username.github.io). - Custom Domain Setup in GitHub Pages:
Add aCNAMEfile to your repository, specifying your custom domain (e.g.,www.yourdomain.com). This informs GitHub Pages about the domain to use when serving your site. - Enabling HTTPS:
GitHub Pages supports HTTPS for custom domains, but SSL certificates need to be correctly issued. You can enable HTTPS in the repository's settings under the GitHub Pages section.
Redirecting to the Preferred Domain:
GitHub Pages doesn't natively support .htaccess redirects, but you can still enforce the correct domain format with these methods:
- Using a Meta Refresh Tag in
index.html:
For simple domain redirects, add the following meta tag in yourindex.htmlfile:<!DOCTYPE html> <html> <head> <meta http-equiv="refresh" content="0; URL=https://www.yourdomain.com"> </head> <body> <p>If you are not redirected, click <a href="https://www.yourdomain.com">here</a>.</p> </body> </html>
For more detailed troubleshooting, consult the official GitHub Pages documentation on custom domains.
Incorrect MIME Types on the Server
Sometimes everything looks right - the CSS file exists, the path in the HTML is correct, and there are no mixed-content issues - but your styles still refuse to load. If you've ruled out the URL prefix problem described above, there's another common culprit: your server is sending the wrong MIME type for your CSS (or JavaScript) files.
What's happening
Every time a browser requests a file from a server, the server includes a Content-Type header in the response. This header tells the browser what kind of file it's receiving. For CSS files, the correct value is text/css. For JavaScript, it should be application/javascript.
Some hosting providers - especially basic or budget shared hosting plans - don't always send the right Content-Type for static files. Instead of text/css, the server might respond with text/plain or even application/octet-stream. When the browser sees this, it treats the file as plain text rather than a stylesheet and simply ignores all the CSS rules inside it.
The result? Your page loads with no styling at all - just raw, unstyled HTML - even though the CSS file is clearly there and contains valid rules.
How to confirm this is the issue
Open your website in Chrome (or any Chromium-based browser), then:
- Press F12 to open DevTools.
- Go to the Network tab.
- Reload the page (Ctrl+Shift+R for a hard refresh).
- Find the
style.cssfile in the list of requests and click on it. - Look at the Response Headers section.
If the Content-Type header says text/plain instead of text/css, you've found the problem. You may also see a warning in the Console tab that looks something like this:
Refused to apply style from 'https://yourdomain.com/assets/css/style.css' because its MIME type ('text/plain') is not a supported stylesheet MIME type, and strict MIME checking is enabled.How to fix it
Apache server (FTP hosting)
Add the following lines to your .htaccess file in the root directory of your website:
AddType text/css .css
AddType application/javascript .js
This explicitly tells Apache to serve .css files with the correct text/css MIME type and .js files as application/javascript.
Nginx server
If your hosting runs Nginx, make sure the mime.types file includes the correct entries. In most cases, the default Nginx configuration already handles this correctly. If it doesn't, you can add the following inside your server block:
location ~* \.css$ {
add_header Content-Type text/css;
}
location ~* \.js$ {
add_header Content-Type application/javascript;
}
Netlify, GitHub Pages, and Vercel
These platforms handle MIME types automatically and correctly out of the box. If you're hosting on one of them and still experiencing this issue, the problem is almost certainly the URL prefix mismatch described earlier in this article, not a MIME type issue.
Tip: After making changes to your .htaccess or server configuration, always do a hard refresh (Ctrl+Shift+R) in your browser. Cached responses with the old Content-Type may persist until you clear them.
Key Takeaway
The key solution is to enforce a consistent URL structure for your website. By implementing redirect rules either in .htaccess or through the configuration settings of your chosen hosting platform, you ensure that users are always directed to the correct version of your website, eliminating the inconsistencies that cause asset loading issues. Remember to choose a preferred URL format (e.g., https://www.yourdomain.com) and consistently redirect all other variations to it. This fixes the asset loading problem and improves your website's SEO and user experience.