I recently encountered a frustrating issue where syntax highlighting worked perfectly when running zola serve locally, but completely disappeared when deployed to Cloudflare Pages. Here's how I diagnosed and fixed the problem.

The Symptoms

The issue manifested in two ways:

  1. Visual difference: Locally, my code blocks had proper syntax highlighting with colors, but on the deployed site, they appeared as plain text with no styling.

  2. HTML inspection revealed the problem: When I examined the generated HTML locally, I could see inline styles with color properties:

<span style="color:#bf616a;">#!/bin/bash</span>

But on the Cloudflare Pages deployment, the same elements had empty style attributes:

<span style="">#!/bin/bash</span>

Initial Investigation

My first assumption was that this was a Zola build configuration issue. I was using Cloudflare Pages with a custom build setup via UNSTABLE_PRE_BUILD:

asdf plugin add zola https://github.com/salasrod/asdf-zola && asdf install zola 0.20.0 && asdf global zola 0.20.0

I initially suspected:

  • Missing CSS generation during build
  • Incorrect config.toml settings for syntax highlighting
  • Build environment differences between local and Cloudflare

The Real Culprit: Content Security Policy

The breakthrough came when I checked the browser console and found multiple CSP (Content Security Policy) errors:

Content-Security-Policy: The page's settings blocked an inline style (style-src-attr) from being applied because it violates the following directive: "style-src 'self'"

Additional related errors included:

Loading failed for the <script> with source "https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015".
Content-Security-Policy: The page's settings blocked a script (script-src-elem) at https://static.cloudflareinsights.com/beacon.min.js/... from being executed because it violates the following directive: "script-src 'self'"
Content-Security-Policy: The page's settings blocked a style (style-src-elem) at https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap from being applied because it violates the following directive: "style-src 'self'"

The Root Cause

The issue wasn't with Zola's build process at all. Cloudflare Pages was correctly generating the HTML with inline styles, but my overly restrictive Content Security Policy was stripping them out at runtime.

My original _headers file was:

/*
  X-Frame-Options: DENY
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; style-src 'self'; img-src 'self'; frame-ancestors 'none';
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

The style-src 'self' directive was blocking all inline styles, including Zola's syntax highlighting.

The Solution

I updated my static/_headers file to allow the necessary resources while maintaining security:

/*
  X-Frame-Options: DENY
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  Content-Security-Policy: default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self'; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://cloudflareinsights.com; frame-ancestors 'none';
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

Key Changes Made

  1. 'unsafe-inline' in style-src: Allows Zola's inline syntax highlighting styles
  2. https://fonts.googleapis.com in style-src: Permits Google Fonts CSS
  3. https://fonts.gstatic.com in font-src: Allows Google Fonts files to load
  4. https://static.cloudflareinsights.com in script-src: Enables Cloudflare Analytics
  5. https://cloudflareinsights.com in connect-src: Allows analytics connections

Lessons Learned

  1. Browser console is your friend: The CSP errors in the console immediately pointed to the real issue, saving hours of debugging Zola configuration.

  2. Security vs. functionality trade-offs: While 'unsafe-inline' reduces security slightly, it's necessary for many static site generators that rely on inline styles.

  3. Test in production: Issues like this only surface in the deployed environment, not during local development.

  4. CSP debugging: Tools like curl -I can help verify which headers are being served:

    curl -I https://peterbabic.dev | grep -i content-security-policy
    

After deploying the updated headers, syntax highlighting worked perfectly, and all console errors disappeared. The fix was simple once the real problem was identified – sometimes the issue isn't where you first expect it to be. Enjoy!