<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mike</title>
    <description>The latest articles on DEV Community by Mike (@mikecube).</description>
    <link>https://dev.to/mikecube</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3970547%2F90fffefa-7fc1-4636-a5c4-575f6632e193.png</url>
      <title>DEV Community: Mike</title>
      <link>https://dev.to/mikecube</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikecube"/>
    <language>en</language>
    <item>
      <title>Astro + Cloudflare Pages: 3 Deploy Bugs You'll Probably Hit</title>
      <dc:creator>Mike</dc:creator>
      <pubDate>Sat, 06 Jun 2026 00:31:39 +0000</pubDate>
      <link>https://dev.to/mikecube/astro-cloudflare-pages-3-deploy-bugs-youll-probably-hit-3e5o</link>
      <guid>https://dev.to/mikecube/astro-cloudflare-pages-3-deploy-bugs-youll-probably-hit-3e5o</guid>
      <description>&lt;p&gt;I've been building a static Astro site on Cloudflare Pages over the last few weeks. Sharing the 3 deployment bugs that cost me the most time, in case they save anyone else the same loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Astro 5 + Cloudflare Pages + Tailwind 4. Content lives in a few JSON files; each page is a dynamic route mapped over the data. Free-tier hosting, no backend. Standard static-first stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug 1: Trailing-slash 307 chain
&lt;/h2&gt;

&lt;p&gt;I started with &lt;code&gt;trailingSlash: 'never'&lt;/code&gt; in Astro config. Build output went to &lt;code&gt;dist/foo/index.html&lt;/code&gt;. Result: Astro emitted canonical tags as &lt;code&gt;/foo&lt;/code&gt; (no slash), but Cloudflare Pages served &lt;code&gt;/foo/&lt;/code&gt; (auto-adding the slash via 307). Google Search Console flagged pages as "Redirect error" because the canonical URL pointed at a redirect chain instead of a real 200.&lt;/p&gt;

&lt;p&gt;I first tried &lt;code&gt;build.format: 'file'&lt;/code&gt; to get flat &lt;code&gt;dist/foo.html&lt;/code&gt; output, hoping that would bypass the trailing slash. That made it worse — Cloudflare still 307-stripped, but now to a non-existent &lt;code&gt;.html&lt;/code&gt; file → 404.&lt;/p&gt;

&lt;p&gt;Fix: stop fighting the platform.&lt;/p&gt;

&lt;p&gt;​&lt;code&gt;js&lt;br&gt;
// astro.config.mjs&lt;br&gt;
export default defineConfig({&lt;br&gt;
  trailingSlash: 'always',&lt;br&gt;
  // ...&lt;br&gt;
});&lt;br&gt;
​&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;trailingSlash: 'always'&lt;/code&gt; plus default directory build aligns the canonical URL with what Pages actually serves. The redirect errors resolved on next re-crawl.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug 2: _redirects rejected at deploy
&lt;/h2&gt;

&lt;p&gt;I tried to do a www → apex 301 in &lt;code&gt;public/_redirects&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://www.example.com/*  https://example.com/:splat  301!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Cloudflare rejected the deploy with three validation errors:&lt;/p&gt;

&lt;p&gt;​&lt;code&gt;&lt;br&gt;
Line 13: Only relative URLs are allowed.&lt;br&gt;
Line 22: Duplicate rule for path /foo.&lt;br&gt;
Line 23: Duplicate rule for path /bar.&lt;br&gt;
​&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pages tightened &lt;code&gt;_redirects&lt;/code&gt; validation — absolute-URL sources aren't accepted anymore. The duplicate errors were because Astro's own &lt;code&gt;redirects&lt;/code&gt; config in &lt;code&gt;astro.config.mjs&lt;/code&gt; generates HTML meta-refresh files that Pages parses as implicit redirect rules — conflicting with my explicit ones.&lt;/p&gt;

&lt;p&gt;Fix: delete &lt;code&gt;_redirects&lt;/code&gt; entirely. Use a Cloudflare Redirect Rule from the dashboard for cross-host 301s (Wildcard pattern, Dynamic destination with &lt;code&gt;${1}&lt;/code&gt; to preserve the path). Astro's HTML-redirect generation handles the in-config aliases on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug 3: Asset manifest staleness across deploys
&lt;/h2&gt;

&lt;p&gt;After switching between &lt;code&gt;build.format: 'file'&lt;/code&gt; and back to directory output, some nested paths started returning 308 → no-slash → 404. Even brand-new URLs that had never been deployed before. Local build output was correct — the live response was stripping the trailing slash on specific nested patterns.&lt;/p&gt;

&lt;p&gt;Turned out to be a stale asset manifest from the previous build mode. Pages was still serving 308s for old &lt;code&gt;.html&lt;/code&gt; file paths even though those files no longer existed in the current deploy.&lt;/p&gt;

&lt;p&gt;Fix: push any commit that triggers a full Pages rebuild — the manifest regenerates cleanly. If you don't have a pending change, an empty commit works:&lt;/p&gt;

&lt;p&gt;​&lt;code&gt;sh&lt;br&gt;
git commit --allow-empty -m "force rebuild"&lt;br&gt;
git push&lt;br&gt;
​&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pick a URL convention (slash or no slash) &lt;strong&gt;before&lt;/strong&gt; deploying to Pages. Switching mid-flight leaves cached redirects that take a full rebuild to clear.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_redirects&lt;/code&gt; is more restricted than the docs suggest. Use dashboard Redirect Rules for anything cross-host.&lt;/li&gt;
&lt;li&gt;GSC's "Redirect error" category is the canary for canonical / serve-URL mismatches. Worth checking weekly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build-in-public log lives on &lt;a href="https://contractorranks.com/" rel="noopener noreferrer"&gt;my site&lt;/a&gt; if you want to follow along.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>buildinpublic</category>
      <category>astro</category>
    </item>
  </channel>
</rss>
