<?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: Leo Zhang</title>
    <description>The latest articles on DEV Community by Leo Zhang (@leo_zhang_0141218398e1788).</description>
    <link>https://dev.to/leo_zhang_0141218398e1788</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%2F3972549%2F06d2dd28-b6b0-4182-99fb-126053f4d303.jpg</url>
      <title>DEV Community: Leo Zhang</title>
      <link>https://dev.to/leo_zhang_0141218398e1788</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leo_zhang_0141218398e1788"/>
    <language>en</language>
    <item>
      <title>Fixing the Tauri v2 white screen in production (and the 6 release bugs right behind it)</title>
      <dc:creator>Leo Zhang</dc:creator>
      <pubDate>Sun, 07 Jun 2026 13:28:33 +0000</pubDate>
      <link>https://dev.to/leo_zhang_0141218398e1788/fixing-the-tauri-v2-white-screen-in-production-and-the-6-release-bugs-right-behind-it-16jk</link>
      <guid>https://dev.to/leo_zhang_0141218398e1788/fixing-the-tauri-v2-white-screen-in-production-and-the-6-release-bugs-right-behind-it-16jk</guid>
      <description>&lt;p&gt;Your Tauri app runs perfectly with &lt;code&gt;tauri dev&lt;/code&gt;. You build it, double-click the bundle, and... a blank white window. Welcome to the part of shipping a desktop app nobody warns you about: &lt;strong&gt;the release.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below are the release issues that eat the most time, with fixes you can paste in. The white screen goes first, because everyone hits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;White screen in prod&lt;/strong&gt; -&amp;gt; your assets load from the wrong place. Set Vite &lt;code&gt;base: './'&lt;/code&gt;, fix &lt;code&gt;frontendDist&lt;/code&gt;, switch the router to hash history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;macOS "app is damaged"&lt;/strong&gt; -&amp;gt; it isn't; it's unsigned and quarantined. &lt;code&gt;xattr -cr&lt;/code&gt; unblocks testers; sign + notarize for the real fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows SmartScreen&lt;/strong&gt; -&amp;gt; unsigned binaries have no reputation. Sign with a cert (an EV cert clears the warning instantly).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The white screen
&lt;/h2&gt;

&lt;p&gt;The bundled webview doesn't load assets from a web-server root - it serves them over a custom protocol. Front-end builds that emit &lt;strong&gt;absolute&lt;/strong&gt; paths (&lt;code&gt;/assets/index.js&lt;/code&gt;) resolve to the wrong place, and SPA routers in history mode hit the same wall.&lt;/p&gt;

&lt;p&gt;Fix it in three moves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// emit ./assets/... instead of /assets/...&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;src-tauri/tauri.conf.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"frontendDist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"beforeBuildCommand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run build"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you use a router, switch it to &lt;strong&gt;hash history&lt;/strong&gt; so deep links resolve inside the webview.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. macOS says your app is "damaged"
&lt;/h2&gt;

&lt;p&gt;It isn't. An unsigned/un-notarized app gets quarantined by Gatekeeper, and the error message is misleading. For a tester right now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xattr &lt;span class="nt"&gt;-cr&lt;/span&gt; &lt;span class="s2"&gt;"/Applications/YourApp.app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real fix is a Developer ID Application certificate ($99/yr Apple Developer account) plus notarization. With the Apple env vars present (&lt;code&gt;APPLE_CERTIFICATE&lt;/code&gt;, &lt;code&gt;APPLE_SIGNING_IDENTITY&lt;/code&gt;, &lt;code&gt;APPLE_ID&lt;/code&gt;, &lt;code&gt;APPLE_PASSWORD&lt;/code&gt;, &lt;code&gt;APPLE_TEAM_ID&lt;/code&gt;), &lt;code&gt;tauri build&lt;/code&gt; signs and notarizes for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Windows SmartScreen blocks the installer
&lt;/h2&gt;

&lt;p&gt;Unsigned binaries have no reputation, so SmartScreen warns until enough people install - or until you sign with a recognized cert. An OV cert earns trust slowly; an EV cert clears the warning immediately. Configure it in the bundle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"windows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"certificateThumbprint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;THUMBPRINT&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"digestAlgorithm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestampUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://timestamp.digicert.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The other four
&lt;/h2&gt;

&lt;p&gt;These three are just the start. The ones that bite next:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Two windows / single-instance race&lt;/strong&gt; - register &lt;code&gt;tauri-plugin-single-instance&lt;/code&gt; &lt;em&gt;first&lt;/em&gt;, before any other plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An updater that silently never fires&lt;/strong&gt; - the keypair, the public key in config, and &lt;code&gt;latest.json&lt;/code&gt;'s signatures must all come from the same key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DMG builds hanging in CI&lt;/strong&gt; - the pretty DMG drives Finder via AppleScript; headless runners have no Finder session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrong identifier / missing resources&lt;/strong&gt; - never ship &lt;code&gt;com.tauri.dev&lt;/code&gt;; declare every &lt;code&gt;resource&lt;/code&gt;/&lt;code&gt;externalBin&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wrote all seven up with paste-in fixes, a signed cross-platform GitHub Actions &lt;code&gt;release.yml&lt;/code&gt;, a secrets table, and a pre-flight checklist in a small kit: &lt;strong&gt;Tauri v2 Ship-It Kit&lt;/strong&gt; - launch price &lt;strong&gt;$12 for the first 50&lt;/strong&gt; -&amp;gt; &lt;a href="https://zhlwave4.gumroad.com/l/iazysv/SHIPIT" rel="noopener noreferrer"&gt;https://zhlwave4.gumroad.com/l/iazysv/SHIPIT&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Either way, save yourself the 2am debugging.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built for Tauri v2. Confirm Apple/Microsoft signing specifics against the official docs before a public launch.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>rust</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
