PageSourceSearch

https://www.artmann.co/articles/signing-notarizing-and-publishing-an-electron-app-for-mac-os

html artmann.co collected 2026-10-03 22:03:08 UTC 156,708 bytes, 340 lines download raw bytes

1<!DOCTYPE html><html lang="en" class="inter_ad991c7-module__LhgUwq__variable poppins_27c1d5ca-module__9rNIbG__variable"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/47fe1b7cd6e6ed85-s.p.0~mcdl10zdfb3.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/83afe278b6a6bb3c-s.p.0q-301v4kxxnr.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/8e6fa89aa22d24ec-s.p.0uvzar8hswo3p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/a218039a3287bcfd-s.p.17-1enzs_j91b.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/e2334d715941921e-s.p.12skym0rqknxy.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp" as="image"/><link rel="preload" href="/images/christoffer-artmann.jpg" as="image"/><link rel="stylesheet" href="/_next/static/chunks/0bl-o8y0lf_g0.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/04hv0w2~6vxm4.js"/>
1<script src="/_next/static/chunks/0yn_1mh.2yy15.js" async=""></script>
1<script src="/_next/static/chunks/0smr7ha0~sd20.js" async=""></script>
1<script src="/_next/static/chunks/04-8xecfnejd~.js" async=""></script>
1<script src="/_next/static/chunks/01tg0hkkqoaeh.js" async=""></script>
1<script src="/_next/static/chunks/turbopack-0be2gka.g7odp.js" async=""></script>
1<script src="/_next/static/chunks/1539c1wk17cta.js" async=""></script>
1<script src="/_next/static/chunks/0d3shmwh5_nmn.js" async=""></script>
1<script src="/_next/static/chunks/0x7k4xycyd2~c.js" async=""></script>
1<link rel="preload" href="https://www.googletagmanager.com/gtag/js?id=UA-34648805-1" as="script"/><meta name="next-size-adjust" content=""/><title>Signing, Notarizing, and Publishing an Electron App for macOS</title><meta name="description" content="I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here&#x27;s everything I had to figure out to fix it."/><meta property="og:title" content="Signing, Notarizing, and Publishing an Electron App for macOS"/><meta property="og:description" content="I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here&#x27;s everything I had to figure out to fix it."/><meta property="og:url" content="https://www.artmann.co/articles/signing-notarizing-and-publishing-an-electron-app-for-mac-os"/><meta property="og:image" content="https://www.artmann.co/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Signing, Notarizing, and Publishing an Electron App for macOS"/><meta name="twitter:description" content="I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here&#x27;s everything I had to figure out to fix it."/><meta name="twitter:image" content="https://www.artmann.co/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-32x32.png" type="image/png" sizes="32x32"/><link rel="icon" href="/favicon-16x16.png" type="image/png" sizes="16x16"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/>
1<script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script>
1</head><body class="text-gray-700 antialiased"><div hidden=""><!--$--><!--/$--></div><!--$!--><template data-dgst="BAILOUT_TO_CLIENT_SIDE_RENDERING"></template><!--/$--><div class="
2        w-full
3        box-border
4        px-8 py-2 md:py-3
5        fixed top-0
6        z-20
7        text-white
8      " id="site-header" style="backdrop-filter:blur(24px);background-color:rgba(113, 34,47, 0.95)"><canvas aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full"></canvas><div class="
9          relative z-10
10          w-full
11          flex items-center
12          max-w-4xl
13          mx-auto
14        "><div class="flex-1"><a class="text-sm font-semibold" style="font-family:var(--font-poppins)" href="/">Christoffer Artmann</a></div><nav class="
15            flex gap-4
16            font-medium
17            text-xs
18          "><div><a class="hover:underline" href="/">Posts</a></div><div><a class="hover:underline" href="/projects">Projects</a></div></nav></div></div><div aria-hidden="true" class="pointer-events-none fixed inset-x-0 z-30 xl:hidden"><div class="relative h-0.5 w-full"><div class="h-full w-full origin-left" style="background:linear-gradient(90deg, #2b0e14, #f59e0b);transform:scaleX(0)"></div><div class="reading-ember absolute -top-0.5 left-0 h-1.5 w-1.5 rounded-full" style="background:#fbbf24"></div></div></div><div aria-hidden="true" class="margin-companions pointer-events-none fixed inset-0 z-10 hidden xl:block"><div class="absolute inset-y-0 left-0 w-36"><div class="dusk-layer-amber"></div><div class="dusk-layer-plum"></div></div><div class="dusk-strip-right absolute inset-y-0 right-0 w-36"><div class="dusk-layer-amber"></div><div class="dusk-layer-plum"></div><canvas aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full"></canvas><span class="dusk-star" style="right:44px;top:14vh"><span class="dusk-star-core"></span></span><span class="dusk-star" style="right:104px;top:26vh"><span class="dusk-star-core" style="animation-delay:2.2s"></span></span></div><div class="absolute left-4 top-[22vh] h-[56vh] w-14"><svg class="h-full w-full" preserveAspectRatio="none" viewBox="0 0 56 400"><defs><mask id="trail-walked-mask"><path d="M 32 10 C 14 54, 46 92, 28 138 S 12 226, 30 268 S 44 330, 27 360" fill="none" pathLength="100" stroke="white" stroke-dasharray="100 100" stroke-dashoffset="100" stroke-width="8" vector-effect="non-scaling-stroke"></path></mask></defs><path d="M 32 10 C 14 54, 46 92, 28 138 S 12 226, 30 268 S 44 330, 27 360" fill="none" pathLength="100" stroke="#71222f" stroke-dasharray="1.1 1.7" stroke-linecap="round" stroke-opacity="0.13" stroke-width="1.5" vector-effect="non-scaling-stroke"></path><path d="M 32 10 C 14 54, 46 92, 28 138 S 12 226, 30 268 S 44 330, 27 360" fill="none" mask="url(#trail-walked-mask)" pathLength="100" stroke="#d97706" stroke-dasharray="1.1 1.7" stroke-linecap="round" stroke-opacity="0.55" stroke-width="1.5" vector-effect="non-scaling-stroke"></path><g transform="translate(28 378)"><circle class="trail-tent-glow trail-tent-glow-outer" fill="#fbbf24" r="10"></circle><circle class="trail-tent-glow trail-tent-glow-inner" fill="#fbbf24" r="5"></circle><path class="trail-tent-lines" d="M-9 6 L0 -7 L9 6 Z" fill="none" stroke-linejoin="round" stroke-width="1.5" vector-effect="non-scaling-stroke"></path><path class="trail-tent-lines" d="M-2.5 6 L0 1.5 L2.5 6" fill="none" stroke-linejoin="round" stroke-width="1.2" vector-effect="non-scaling-stroke"></path></g></svg><div class="reading-ember absolute left-0 top-0 h-1.5 w-1.5 rounded-full" style="background:#fbbf24"></div></div></div><div class="container mx-auto p-4 pb-8 md:py-8 max-w-4xl"><article class="w-full text-gray-800 leading-loose pt-16 md:pt-24 space-y-8"><header class="space-y-3"><h1 class="text-2xl md:text-3xl font-semibold">Signing, Notarizing, and Publishing an Electron App for macOS</h1><p class="text-lg md:text-xl">I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here&#x27;s everything I had to figure out to fix it.</p><p class="mb-8 text-sm text-gray-600">August 03, 2026</p></header><img alt="Signing, Notarizing, and Publishing an Electron App for macOS" class="w-full h-auto border-gray-300 shadow-lg overflow-x-hidden break-words" src="/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp"/><div class="article-content text-base leading-relaxed text-gray-900 pb-8 md:pb-16"><p>I shipped a macOS build of <a href="https://github.com/Artmann/squeal">Squeal</a>, a SQL
19client I&#39;m building, and it was completely unusable. CI was green, the release
20page had a nice <code>.zip</code> attached, and every single person who downloaded it got
21the same dialog:</p>
22<blockquote>
23<p>&quot;Squeal.app&quot; is damaged and can&#39;t be opened. You should move it to the Trash.</p>
24</blockquote>
25<p>Nothing was damaged. The download was fine. That message is macOS being
26unhelpful about a code signing problem, and it took me way longer than it should
27have to work that out, mostly because every Electron tutorial I could find stops
28at <code>electron-forge make</code> and never mentions signing at all.</p>
29<p>So here&#39;s the config I ended up with, and all the traps I walked into on the
30way.</p>
31<p>Let&#39;s start with why that error message lies to you. &quot;Damaged&quot; sounds like a
32corrupt download or a bad zip, right? It isn&#39;t. What it actually means is that
33Gatekeeper took a look at your app&#39;s code signature and decided it wasn&#39;t valid.</p>
34<p>When you download a file in a browser, macOS attaches a <code>com.apple.quarantine</code>
35extended attribute to it, and on first launch Gatekeeper checks the signature of
36anything carrying that flag. If there&#39;
36s no signature at all, you get the
37friendly &quot;unidentified developer&quot; dialog with a right-click-to-open escape
38hatch. But if there&#39;s a signature that fails validation, you get &quot;damaged&quot;, and
39there&#39;s no escape hatch at all.</p>
40<p>The good news is that you don&#39;t have to guess which one you&#39;re hitting. You can
41reproduce the whole thing locally in two commands. Copy your built app, mark it
42as quarantined, and ask Gatekeeper directly:</p>
43<pre><code class="hljs language-bash"><span class="hljs-built_in">cp</span> -R out/MyApp-darwin-arm64/MyApp.app /tmp/qt.app
44xattr -w com.apple.quarantine <span class="hljs-string">&quot;0083;00000000;Safari;&quot;</span> /tmp/qt.app
45spctl --assess --<span class="hljs-built_in">type</span> execute --verbose /tmp/qt.app
46</code></pre><p>On my broken build, that printed:</p>
47<pre><code class="hljs language-text">/tmp/qt.app: invalid Info.plist (plist or signature have been modified)
48</code></pre><p>There it is. Not a damaged download, just a signature that doesn&#39;t match the
49app. And once I signed things properly, the exact same command on the exact same
50quarantined copy printed:</p>
51<pre><code class="hljs language-text">/tmp/qt.app: accepted
52source=Developer ID
53</code></pre><p>Run that against every build before you publish it.</p>
54<p>Now here&#39;s the part that genuinely surprised me, and it&#39;s specific to Electron.</p>
55<p>You&#39;d expect an app you never signed to simply have no signature, right? But
56Electron&#39;s prebuilt binaries ship with an ad-hoc signature already applied, and
57the fuses plugin destroys it. You probably use that plugin, by the way, since it
58comes with the default template.</p>
59<p>Fuses are build-time feature flags that toggle things like <code>RunAsNode</code> and
60<code>EnableNodeCliInspectArguments</code>, and the way they work is by rewriting bytes
61inside the Electron binary. Functionally that&#39;s completely fine. But flipping a
62byte inside a signed binary invalidates its signature.</p>
63<p>So an unsigned Electron app isn&#39;t really unsigned at all. It&#39;s carrying a
64signature that actively fails validation, which is exactly why macOS reaches for
65&quot;damaged&quot; instead of the much friendlier &quot;unidentified developer&quot;. Two perfectly
66reasonable decisions — use the fuses plugin, don&#39;t bother signing while you&#39;re
67developing — combine into one very confusing failure.</p>
68<p>The fix is to sign the app for real.</p>
69<p>Let&#39;s start with the certificate. You need a paid Apple Developer Program
70membership, and there&#39;s no free path here, because notarization requires an
71Apple ID attached to a real team.</p>
72<p>Once you&#39;re in, create a <strong>Developer ID Application</strong> certificate. Not &quot;Mac App
73Distribution&quot;, not &quot;Apple Development&quot; — those are for the Mac App Store and for
74local testing. Developer ID is the one for apps you hand out yourself.</p>
75<p>Install it, then confirm your machine can actually sign with it:</p>
76<pre><code class="hljs language-bash">security find-identity -v -p codesigning
77</code></pre><pre><code class="hljs language-text">1) A8A50AAB447134FA3856408FD4030C6D5A6D95E5 &quot;Developer ID Application: Your Company (TEAMID)&quot;
78   1 valid identities found
79</code></pre><p>If your certificate doesn&#39;t show up in that list, the private key is missing,
80and a certificate without its key can&#39;t sign anything. You&#39;ll need to
81re-download it using the original CSR, or generate a new one.</p>
82<p>That <code>TEAMID</code> in the parentheses is your team ID. Write it down, you&#39;ll need it
83a few times.</p>
84<p>With the certificate installed we can configure signing, which lives in
85<code>packagerConfig</code> in your <code>forge.config.ts</code>. Notice that I gate the whole thing
86on an environment variable:</p>
87<pre><code class="hljs language-typescript"><span class="hljs-attr">packagerConfig</span>: {
88  <span class="hljs-attr">appBundleId</span>: <span class="hljs-string">&#x27;co.example.myapp&#x27;</span>,
89  <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;./assets/icons/icon&#x27;</span>,
90  ...(process.<span class="hljs-property">
90env</span>.<span class="hljs-property">APPLE_TEAM_ID</span> &amp;&amp; {
91    <span class="hljs-attr">osxSign</span>: {
92      <span class="hljs-attr">identity</span>: <span class="hljs-string">&#x27;Developer ID Application&#x27;</span>,
93      <span class="hljs-attr">optionsForFile</span>: <span class="hljs-function">(<span class="hljs-params"><span class="hljs-attr">filePath</span>: <span class="hljs-built_in">string</span></span>) =&gt;</span> {
94        <span class="hljs-keyword">const</span> isMainAppBundle =
95          filePath.<span class="hljs-title function_">endsWith</span>(<span class="hljs-string">&#x27;.app&#x27;</span>) &amp;&amp; !filePath.<span class="hljs-title function_">includes</span>(<span class="hljs-string">&#x27;Helper&#x27;</span>)
96
97        <span class="hljs-keyword">return</span> {
98          <span class="hljs-attr">hardenedRuntime</span>: <span class="hljs-literal">true</span>,
99          ...(isMainAppBundle &amp;&amp; {
100            <span class="hljs-attr">entitlements</span>: <span class="hljs-title function_">resolve</span>(<span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">dirname</span>, <span class="hljs-string">&#x27;entitlements.plist&#x27;</span>)
101          })
102        }
103      }
104    },
105    <span class="hljs-attr">osxNotarize</span>: {
106      <span class="hljs-attr">appleId</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">APPLE_ID</span> ?? <span class="hljs-string">&#x27;&#x27;</span>,
107      <span class="hljs-attr">appleIdPassword</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">APPLE_APP_SPECIFIC_PASSWORD</span> ?? <span class="hljs-string">&#x27;&#x27;</span>,
108      <span class="hljs-attr">teamId</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">APPLE_TEAM_ID</span>
109    }
110  })
111}
112</code></pre><p>That gate on <code>APPLE_TEAM_ID</code> matters more than it looks. Without it, nobody can
113build your app unless they have your certificate, which breaks contributors,
114forks, and your own quick local builds. With the gate, <code>yarn make</code> works
115everywhere and signing only kicks in when the credentials are actually there.</p>
116<p>You&#39;ll also want to set <code>appBundleId</code> explicitly, because the default is
117<code>com.electron.&lt;name&gt;</code> and you really don&#39;t want that out in the wild. It has to
118stay stable forever, too. Notarization and keychain access both key off it, so
119changing it later orphans anything your app stored in the keychain.</p>
120<p>And <code>optionsForFile</code> runs for every single binary in the bundle, of which there
121are a lot: helper apps, frameworks, native modules. Entitlements belong on the
122main app bundle only, while the helpers just need the hardened runtime and
123nothing else. Get this wrong and you get mysterious crashes.</p>
124<p>Next up is the entitlements file. Notarization requires the hardened runtime,
125and the hardened runtime happily blocks a bunch of things Electron needs. Create
126<code>entitlements.plist</code> in your project root:</p>
127<pre><code class="hljs language-xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span>?&gt;</span>
128<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">plist</span> <span class="hljs-keyword">PUBLIC</span> <span class="hljs-string">&quot;-//Apple//DTD PLIST 1.0//EN&quot;</span> <span class="hljs-string">&quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;</span>&gt;</span>
129<span class="hljs-tag">&lt;<span class="hljs-name">plist</span> <span class="hljs-attr">version</span>=<span class="hljs-string">&quot;1.0&quot;</span>&gt;</span>
130<span class="hljs-tag">&lt;<span class="hljs-name">dict</span>&gt;</span>
131  <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>com.apple.security.cs.allow-jit<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
132  <span class="hljs-tag">&lt;<span class="hljs-name">true</span>/&gt;</span>
133  <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>com.apple.security.cs.allow-unsigned-executable-memory<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
134  <span class="hljs-tag">&lt;<span class="hljs-name">true</span>/&gt;</span>
135  <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>com.apple.security.cs.disable-library-validation<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
136  <span class="hljs-tag">&lt;<span class="hljs-name">true</span>/&gt;</span>
137<span class="hljs-tag">&lt;/<span class="hljs-name">dict</span>&gt;</span>
138<span class="hljs-tag">&lt;/<span class="hljs-name">plist</span>&gt;</span>
139</code></pre><p>Each key in there fixes something specific:</p>
140<ul>
141<li><strong><code>allow-jit</code></strong> and <strong><code>allow-unsigned-executable-memory</code></strong> — V8 compiles
142JavaScript to machine code at runtime and then runs it, which is precisely
143what the hardened runtime exists to prevent, so you have to ask for an
144exception.</li>
145<li><strong><code>disable-library-validation</code></strong> — this is the one that gets you if you have
146native modules. Library validation refuses to load code signed by a different
147team, so without it any <code>.node</code> binding fails to load and you get a runtime
148crash in a signed build that ran perfectly well unsigned.</li>
149</ul>
150<p>If your app is pure JavaScript with no native dependencies, you can try dropping
151that third one. If you bundle anything with a native binding, keep it.</p>
152<p>That brings us to notarization itself, which is Apple scanning your signed app
153for malware and issuing a ticket that says it passed. Since macOS 10.15 it&#39;s
154effectively mandatory if you want people to be able to open your app at all.</p>
155<p>The <code>osxNotarize</code> block above handles it, but you need an <strong>app-specific
156password</strong>, because your regular Apple ID password will not work:</p>
157<ol>
158<li>Go to <a href="https://appleid.apple.com">appleid.apple.com</a> and sign in</li>
159<li><strong>Sign-In and Security</strong> → <strong>App-Specific Passwords</strong> → <strong>+</strong></li>
160<li>Name it something like <code>myapp-notarization</code></li>
161<li>Copy the <code>xxxx-xxxx-xxxx-xxxx</code> value</li>
162</ol>
163<p>Before you wire this into CI, check that the credentials actually work. It takes
164a few seconds and saves you a failed release:</p>
165<pre><code class="hljs language-bash">xcrun notarytool <span class="hljs-built_in">history</span> --apple-id <span class="hljs-string">&quot;[email protected]&quot;</span> \
166  --password <span class="hljs-string">&quot;xxxx-xxxx-xxxx-xxxx&quot;</span> --team-id TEAMID
167</code></pre><p>If that returns a history, even an empty one, all three notarization credentials
168are correct and work together. An auth error means the password is wrong, or
169your Apple ID doesn&#39;t have the right role on the team — you need to be Account
170Holder, Admin, or App Manager.</p>
171<p>One thing to be aware of is that notarization adds a few minutes to every build.
172It&#39;s an upload, a queue, and a scan, so don&#39;t expect it to be instant.</p>
173<p>Now for what you actually ship. The default Forge template hands macOS users a
174<code>.zip</code>, which makes for a pretty poor first run. The app ends up unzipped in
175Downloads and runs from there, never making it anywhere near the Applications
176folder.</p>
177<p>Use a DMG for the download instead:</p>
178<pre><code class="hljs language-bash">
178yarn add -D @electron-forge/maker-dmg
179</code></pre><pre><code class="hljs language-typescript"><span class="hljs-attr">makers</span>: [
180  <span class="hljs-keyword">new</span> <span class="hljs-title class_">MakerDMG</span>({ <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;./assets/icons/icon.icns&#x27;</span> }, [<span class="hljs-string">&#x27;darwin&#x27;</span>]),
181  <span class="hljs-keyword">new</span> <span class="hljs-title class_">MakerZIP</span>({}, [<span class="hljs-string">&#x27;darwin&#x27;</span>])
182]
183</code></pre><p>Two traps here, and I fell into both.</p>
184<p>The first one is that you shouldn&#39;t set <code>name</code> on <code>MakerDMG</code>. With no <code>name</code>,
185the maker outputs <code>MyApp-&lt;version&gt;-&lt;arch&gt;.dmg</code>, but set one and every
186architecture produces the <em>same</em> filename. Build arm64 and x64 in separate CI
187jobs, upload both to the same release, and the second one quietly overwrites the
188first.</p>
189<p>The second one is to keep the ZIP, even though nothing appears to use it. This
190nearly cost me macOS auto-updates. Squirrel.Mac can&#39;t read a DMG, so if you
191update through <code>autoUpdater</code> or <code>update-electron-app</code>, that zip is the only
192format it can install. Remove the zip maker and macOS updates stop working while
193every build stays green. <code>update.electronjs.org</code> also matches on the filename,
194<code>MyApp-darwin-arm64-&lt;version&gt;.zip</code>, to pick the right architecture.</p>
195<p>So: DMG for humans, ZIP for the updater.</p>
196<p>Before we get to CI, a quick warning about fuses. Once you learn that flipping
197them breaks the ad-hoc signature, the fix looks pretty obvious.
198<code>@electron/fuses</code> has an option for exactly this, so you set it:</p>
199<pre><code class="hljs language-typescript"><span class="hljs-keyword">new</span> <span class="hljs-title class_">FusesPlugin</span>({
200  <span class="hljs-attr">version</span>: <span class="hljs-title class_">FuseVersion</span>.<span class="hljs-property">V1</span>,
201  <span class="hljs-attr">resetAdHocDarwinSignature</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// ← don&#x27;t do this</span>
202  ...
203})
204</code></pre><p>Don&#39;t. I did, then read the plugin&#39;s source and took it straight back out.
205Here&#39;s what <code>@electron-forge/plugin-fuses</code> is already doing for you:</p>
206<pre><code class="hljs language-javascript"><span class="hljs-keyword">await</span> <span class="hljs-title function_">flipFuses</span>(pathToElectronExecutable, {
207  <span class="hljs-attr">resetAdHocDarwinSignature</span>:
208    !hasOSXSignConfig &amp;&amp; applePlatforms.<span class="hljs-title function_">includes</span>(platform) &amp;&amp; arch === <span class="hljs-string">&#x27;arm64&#x27;</span>,
209  ...<span class="hljs-variable language_">this</span>.<span class="hljs-property">fusesConfig</span>
210})
211</code></pre><p>It sets the flag itself, and only when there&#39;s no <code>osxSign</code> config, which is
212exactly the unsigned-local-build case. And notice that <code>...this.fusesConfig</code> is
213spread <em>after</em>, so your value wins and overrides that logic entirely. You&#39;d be
214forcing it on for signed builds too.</p>
215<p>It also can&#39;t do what you&#39;re hoping it does. The plugin runs at
216<code>packageAfterCopy</code>, before Electron Packager rewrites <code>Info.plist</code> with your
217app&#39;s name and bundle ID. So it signs, then the plist changes underneath the
218signature, and you&#39;re right back to an invalid signature. I confirmed this on a
219real build, where the app still reported <code>Identifier=com.github.Electron</code> and
220failed <code>codesign --verify</code>.</p>
221<p>So leave it alone. The valid signature comes from <code>osxSign</code>, which runs at the
222very end of packaging, after everything else has settled down.</p>
223<p>Signing locally is fine for testing, but you want your releases to be
224reproducible, and that means getting your certificate onto a CI runner.</p>
225<p>First, export it. In <strong>Keychain Access</strong>, find your Developer ID Application
226certificate under <strong>login</strong> → <strong>My Certificates</strong>. Expand it and make sure
227there&#39;s a private key underneath. Then right-click → <strong>Export</strong>, choose
228<strong>Personal Information Exchange (.p12)</strong>, and set a strong password.</p>
229<p><img src="/images/blog/keychain-developer-id-certificate.png" alt="The Developer ID Application certificate expanded in Keychain Access, with its private key listed underneath"></p>
230<p>Check that the export actually contains that key, because a cert-only <code>.p12</code>
231fails in CI in a really confusing way:</p>
232<pre><code class="hljs language-bash">openssl pkcs12 -<span class="hljs-keyword">in</span> cert.p12 -info -noout -passin pass:<span class="hljs-string">&#x27;YOUR_PASSWORD&#x27;</span>
233</code></pre><p>You want to see both a <code>certBag</code> and a <code>PKCS8ShroudedKeyBag</code> in there. Then
234base64 it:</p>
235<pre><code class="hljs language-bash"><span class="hljs-built_in">base64</span> -i cert.p12 -o cert.p12.b64
236</code></pre><p>Add five repository secrets: <code>APPLE_CERTIFICATE</code> (the base64 blob),
237<code>APPLE_CERTIFICATE_PASSWORD</code>, <code>APPLE_ID</code>, <code>APPLE_APP_SPECIFIC_PASSWORD</code>, and
238<code>APPLE_TEAM_ID</code>.</p>
239<p>On the runner, the certificate goes into a temporary keychain:</p>
240<pre><code class="hljs language-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">
240Import</span> <span class="hljs-string">Apple</span> <span class="hljs-string">certificate</span>
241  <span class="hljs-attr">if:</span> <span class="hljs-string">startsWith(matrix.os,</span> <span class="hljs-string">&#x27;macos&#x27;</span><span class="hljs-string">)</span>
242  <span class="hljs-attr">env:</span>
243    <span class="hljs-attr">APPLE_CERTIFICATE:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_CERTIFICATE</span> <span class="hljs-string">}}</span>
244    <span class="hljs-attr">APPLE_CERTIFICATE_PASSWORD:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_CERTIFICATE_PASSWORD</span> <span class="hljs-string">}}</span>
245  <span class="hljs-attr">run:</span> <span class="hljs-string">|
246    CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12
247    KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
248    KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
249</span>
250    <span class="hljs-string">echo</span> <span class="hljs-string">-n</span> <span class="hljs-string">&quot;$APPLE_CERTIFICATE&quot;</span> <span class="hljs-string">|</span> <span class="hljs-string">base64</span> <span class="hljs-string">
250--decode</span> <span class="hljs-string">-o</span> <span class="hljs-string">$CERTIFICATE_PATH</span>
251
252    <span class="hljs-string">security</span> <span class="hljs-string">create-keychain</span> <span class="hljs-string">-p</span> <span class="hljs-string">&quot;$KEYCHAIN_PASSWORD&quot;</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
253    <span class="hljs-string">security</span> <span class="hljs-string">set-keychain-settings</span> <span class="hljs-string">-lut</span> <span class="hljs-number">21600</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
254    <span class="hljs-string">security</span> <span class="hljs-string">unlock-keychain</span> <span class="hljs-string">-p</span> <span class="hljs-string">&quot;$KEYCHAIN_PASSWORD&quot;</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
255
256    <span class="hljs-string">security</span> <span class="hljs-string">import</span> <span class="hljs-string">$CERTIFICATE_PATH</span> <span class="hljs-string">-P</span> <span class="hljs-string">&quot;$APPLE_CERTIFICATE_PASSWORD&quot;</span> <span class="hljs-string">\</span>
257      <span class="hljs-string">-A</span> <span class="hljs-string">-t</span> <span class="hljs-string">cert</span> <span class="hljs-string">-f</span> <span class="hljs-string">pkcs12</span> <span class="hljs-string">-k</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
258    <span class="hljs-string">security</span> <span class="hljs-string">set-key-partition-list</span> <span class="hljs-string">-S</span> <span class="hljs-string">apple-tool:,apple:</span> <span class="hljs-string">\</span>
259      <span class="hljs-string">-k</span> <span class="hljs-string">&quot;$KEYCHAIN_PASSWORD&quot;</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
260
261    <span class="hljs-string">security</span> <span class="hljs-string">list-keychain</span> <span class="hljs-string">-d</span> <span class="hljs-string">user</span> <span class="hljs-string">-s</span> <span class="hljs-string">$KEYCHAIN_PATH</span>
262</code></pre><p>That&#39;s a throwaway keychain with a random password, thrown away along with the
263runner. The <code>set-key-partition-list</code> call is the non-obvious one — leave it out
264and <code>codesign</code> hangs forever, waiting for a UI prompt that nobody is ever going
265to answer.</p>
266<p>Then pass the credentials through to the build:</p>
267<pre><code class="hljs language-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">artifacts</span>
268  <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">make</span>
269  <span class="hljs-attr">env:</span>
270    <span class="hljs-attr">APPLE_APP_SPECIFIC_PASSWORD:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_APP_SPECIFIC_PASSWORD</span> <span class="hljs-string">}}</span>
271    <span class="hljs-attr">APPLE_ID:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_ID</span> <span class="hljs-string">}}</span>
272    <span class="hljs-attr">APPLE_TEAM_ID:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_TEAM_ID</span> <span class="hljs-string">}}</span>
273</code></pre><p>If you support Intel Macs, you&#39;ll need a second runner. <code>macos-latest</code> is Apple
274silicon, so that&#39;s the only architecture it can build correctly. Reach for
275<code>--arch=x64</code> and you&#39;ll get a broken app the moment you have native
276dependencies, because those ship per-architecture prebuilt bindings and your
277package manager only installs the one matching the runner.</p>
278<p>Use a separate job instead:</p>
279<pre><code class="hljs language-yaml"><span class="hljs-attr">strategy:</span>
280  <span class="hljs-attr">matrix:</span>
281    <span class="hljs-attr">os:</span> [<span class="hljs-string">macos-latest</span>, <span class="hljs-string">macos-15-intel</span>]
282</code></pre><p><code>macos-15-intel</code> is GitHub&#39;s Intel image, and it&#39;s worth knowing that it&#39;s the
283last one. It&#39;s available until August 2027, and after that x86_64 isn&#39;t
284supported on GitHub Actions at all.</p>
285<p>There are also two guards worth adding, because that environment-variable gate
286has a nasty edge to it. If a secret goes missing in CI, <code>osxSign</code> never runs and
287you happily publish an unsigned app. That&#39;s the exact bug you set out to fix,
288except now the release looks like a success.</p>
289<p>So check for them explicitly:</p>
290<pre><code class="hljs language-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Check</span> <span class="hljs-string">
290Apple</span> <span class="hljs-string">signing</span> <span class="hljs-string">secrets</span>
291  <span class="hljs-attr">if:</span> <span class="hljs-string">startsWith(matrix.os,</span> <span class="hljs-string">&#x27;macos&#x27;</span><span class="hljs-string">)</span>
292  <span class="hljs-attr">shell:</span> <span class="hljs-string">bash</span>
293  <span class="hljs-attr">env:</span>
294    <span class="hljs-attr">APPLE_TEAM_ID:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.APPLE_TEAM_ID</span> <span class="hljs-string">}}</span>
295    <span class="hljs-comment"># ...and the rest</span>
296  <span class="hljs-attr">run:</span> <span class="hljs-string">|
297    missing=()
298</span>
299    <span class="hljs-string">for</span> <span class="hljs-string">name</span> <span class="hljs-string">in</span> <span class="hljs-string">APPLE_APP_SPECIFIC_PASSWORD</span> <span class="hljs-string">APPLE_CERTIFICATE</span> <span class="hljs-string">\</span>
300      <span class="hljs-string">APPLE_CERTIFICATE_PASSWORD</span> <span class="hljs-string">APPLE_ID</span> <span class="hljs-string">APPLE_TEAM_ID;</span> <span class="hljs-string">do</span>
301      <span class="hljs-string">if</span> [ <span class="hljs-string">-z</span> <span class="hljs-string">&quot;${!name}&quot;</span> ]<span class="hljs-string">;</span> <span class="hljs-string">then</span>
302        <span class="hljs-string">missing+=(&quot;$name&quot;)</span>
303      <span class="hljs-string">fi</span>
304    <span class="hljs-string">done</span>
305
306    <span class="hljs-string">if</span> [ <span class="hljs-string">$</span>{<span class="hljs-comment">#missing[@]} -gt 0 ]; then</span>
307      <span class="hljs-string">echo</span> <span class="hljs-string">&quot;::error::Missing repository secrets: ${missing[*]}. Without them the app is unsigned and macOS reports it as damaged.&quot;</span>
308      <span class="hljs-string">exit</span> <span class="hljs-number">1</span>
309    <span class="hljs-string">fi</span>
310</code></pre><p>While you&#39;re in there, check that the makers actually produced something. A bare
311<code>find -exec</code> exits 0 when nothing matches, so a maker that failed leaves you
312with a green checkmark and a release that has no installer for that platform:</p>
313<pre><code class="hljs language-bash"><span class="hljs-keyword">if</span> [ <span class="hljs-variable">${#artifacts[@]}</span> -eq 0 ]; <span class="hljs-keyword">then</span>
314  <span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;::error::No installers found in out/make. Check the build step.&quot;</span>
315  <span class="hljs-built_in">exit</span> 1
316<span class="hljs-keyword">fi</span>
317</code></pre><p>Both of these guards exist for the same reason. The default behaviour is to fail
318silently, and in a release pipeline that&#39;s the worst kind of failure there is.</p>
319<p>That leaves verification, which is three commands. Run them on the built app and
320actually read the output:</p>
321<pre><code class="hljs language-bash">codesign --verify --deep --strict --verbose=2 out/MyApp-darwin-arm64/MyApp.app
322spctl --assess --<span class="hljs-built_in">type</span> execute --verbose out/MyApp-darwin-arm64/MyApp.app
323xcrun stapler validate out/MyApp-darwin-arm64/MyApp.app
324</code></pre><p>Here&#39;s what you want to see:</p>
325<pre><code class="hljs language-text">MyApp.app: valid on disk
326MyApp.app: satisfies its Designated Requirement
327MyApp.app: accepted
328source=Notarized Developer ID
329</code></pre><p><code>codesign -dv</code> is worth a look too. Check three things: that the identifier is
330your bundle ID and not <code>com.github.Electron</code>, that <code>TeamIdentifier</code> has a value,
331and that the flags read <code>flags=0x10000(runtime)</code>. That last one is your proof
332that the hardened runtime is actually on:</p>
333<pre><code class="hljs language-bash">codesign -dv out/MyApp-darwin-arm64/MyApp.app
334</code></pre><p>Then launch the signed build and click around a bit. This matters more than it
335sounds, because the hardened runtime is exactly where native modules break, and
336a signed app is the first time that code path ever runs. So if you ship a native
337binding, open a connection, read a file, do the thing.</p>
338<p><em>Have you shipped an Electron app to macOS? Let me know in the comments if you
339ran into any traps I missed!</em></p>
340</div><div class="relative flex flex-col items-center gap-3 pb-6 pt-4 text-center"><canvas aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full"></canvas><svg aria-hidden="true" class="" height="44" viewBox="0 0 64 56" width="50.285714285714285"><ellipse class="campfire-glow" cx="32" cy="44" fill="#f97316" rx="22" ry="10"></ellipse><circle class="campfire-spark" cx="26" cy="24" fill="#fbbf24" r="1"></circle><circle class="campfire-spark" cx="39" cy="28" fill="#fcd34d" r="0.8" style="animation-delay:-1.4s"></circle><g class="campfire-flame-outer">
340<path d="M32 12 C38 22 43 30 43 38 C43 45 38 49 32 49 C26 49 21 45 21 38 C21 30 26 22 32 12 Z" fill="#f59e0b"></path></g><g class="campfire-flame-mid"><path d="M32 20 C36 27 39.5 32 39.5 38 C39.5 43.5 36 46.5 32 46.5 C28 46.5 24.5 43.5 24.5 38 C24.5 32 28 27 32 20 Z" fill="#f97316"></path></g><g class="campfire-flame-inner"><path d="M32 29 C34.5 33.5 36 36.5 36 40 C36 43.5 34 45 32 45 C30 45 28 43.5 28 40 C28 36.5 29.5 33.5 32 29 Z" fill="#fde68a"></path></g><rect fill="#4a2f22" height="5" rx="2.5" transform="rotate(14 32 48.5)" width="26" x="19" y="46"></rect><rect fill="#3a241a" height="5" rx="2.5" transform="rotate(-14 32 48.5)" width="26" x="19" y="46"></rect></svg><p class="m-0 text-sm text-gray-500">You&#x27;ve reached camp. Thanks for reading.</p></div></article><div style="color:rgb(55, 65, 81);background-color:rgb(255, 255, 255)"><div id="disqus_thread"></div></div></div><footer class="mt-8"><div class="-mb-px"><svg aria-hidden="true" class="block h-8 w-full text-burgundy sm:h-12 md:h-16" preserveAspectRatio="none" viewBox="0 0 1200 80"><path d="M-10,90 L-10,79 L-15.6,79 L-7.4,63.7 L-10.5,65.4 L-8.8,64.5 L-2.3,52.8 L-5.4,54.5 L-3.7,53.6 L1.5,42.7 L6.6,53.6 L8.3,54.5 L5.2,52.8 L11.7,64.5 L13.4,65.4 L10.3,63.7 L18.6,79 L8.6,79 L16.7,65.1 L13.7,66.6 L15.4,65.8 L21.8,55.2 L18.7,56.7 L20.4,55.9 L25.5,45.9 L30.6,55.9 L32.3,56.7 L29.2,55.2 L35.7,65.8 L37.3,66.6 L34.3,65.1 L42.4,79 L30.2,79 L39.4,69.6 L36,70.6 L37.9,70.1 L45.1,62.9 L41.7,63.9 L43.6,63.3 L49.3,56.6 L55,63.3 L57,63.9 L53.5,62.9 L60.8,70.1 L62.7,70.6 L59.2,69.6 L68.4,79 L49.8,79 L60.1,69.5 L56.3,70.5 L58.4,69.9 L66.6,62.7 L62.7,63.7 L64.9,63.1 L71.4,56.4 L77.8,63.1 L80,63.7 L76.1,62.7 L84.3,69.9 L86.5,70.5 L82.6,69.5 L92.9,79 L76.4,79 L85.6,70.5 L82.1,71.4 L84,70.9 L91.3,64.5 L87.9,65.4 L89.8,64.9 L95.5,58.8 L101.3,64.9 L103.2,65.4 L99.7,64.5 L107,70.9 L108.9,71.4 L105.5,70.5 L114.7,79 L96.7,79 L105.1,71.2 L101.9,72 L103.7,71.6 L110.3,65.6 L107.2,66.5 L108.9,66 L114.1,60.4 L119.3,66 L121.1,66.5 L118,65.6 L124.6,71.6 L126.3,72 L123.2,71.2 L131.5,79 L115.9,79 L123.9,71.9 L120.9,72.6 L122.6,72.2 L129,66.8 L126,67.5 L127.6,67.1 L132.7,62 L137.7,67.1 L139.4,67.5 L136.4,66.8 L142.7,72.2 L144.4,72.6 L141.4,71.9 L149.5,79 L131.1,79 L137.7,70.7 L135.2,71.6 L136.6,71.1 L141.8,64.7 L139.4,65.6 L140.7,65.1 L144.9,59.2 L149,65.1 L150.4,65.6 L147.9,64.7 L153.2,71.1 L154.5,71.6 L152.1,70.7 L158.7,79 L149.4,79 L157.5,71.7 L154.5,72.4 L156.2,72 L162.6,66.4 L159.6,67.2 L161.3,66.8 L166.4,61.5 L171.5,66.8 L173.2,67.2 L170.1,66.4 L176.5,72 L178.2,72.4 L175.2,71.7 L183.3,79 L168.1,79 L176.1,71.4 L173.1,72.2 L174.7,71.7 L181,65.9 L178,66.7 L179.7,66.3 L184.7,60.8 L189.6,66.3 L191.3,66.7 L188.3,65.9 L194.6,71.7 L196.3,72.2 L193.3,71.4 L201.3,79 L184.5,79 L193.7,72.3 L190.3,73 L192.2,72.6 L199.5,67.6 L196,68.3 L197.9,67.9 L203.7,63.1 L209.4,67.9 L211.3,68.3 L207.9,67.6 L215.2,72.6 L217.1,73 L213.6,72.3 L222.8,79 L203.5,79 L212.7,70.8 L209.2,71.7 L211.1,71.2 L218.4,65 L215,65.9 L216.9,65.4 L222.6,59.6 L228.3,65.4 L230.3,65.9 L226.8,65 L234.1,71.2 L236,71.7 L232.6,70.8 L241.7,79 L225.5,79 L231.3,71.9 L229.1,72.6 L230.3,72.2 L234.9,66.8 L232.7,67.5 L233.9,67.1 L237.5,62 L241.1,67.1 L242.3,67.5 L240.2,66.8 L244.7,72.2 L245.9,72.6 L243.8,71.9 L249.5,79 L237,79 L243.3,70.9 L240.9,71.8 L242.3,71.3 L247.3,65.1 L244.9,66 L246.2,65.5 L250.2,59.7 L254.2,65.5 L255.5,66 L253.1,65.1 L258.2,71.3 L259.5,71.8 L257.1,70.9 L263.5,79 L256.7,79 L264.4,69.9 L261.5,70.8 L263.1,70.3 L269.1,63.3 L266.3,64.3 L267.9,63.8 L272.6,57.2 L277.4,63.8 L279,64.3 L276.1,63.3 L282.2,70.3 L283.8,70.8 L280.9,69.9 L288.5,79 L274.7,79 L283.2,70.8 L280,71.7 L281.7,71.2 L288.4,64.9 L285.3,65.8 L287,65.3 L292.3,59.5 L297.6,65.3 L299.4,65.8 L296.2,64.9 L302.9,71.2 L304.7,71.7 L301.5,70.8 L310,79 L296.4,79 L306.8,68.5 L302.9,69.6 L305.1,69 L313.3,60.9 L309.4,62.1 L311.6,61.4 L318.1,53.9 L324.6,61.4 L326.7,62.1 L322.8,60.9 L331.1,69 L333.2,69.6 L329.3,68.5 L339.7,79 L324.4,79 L333,68.5 L329.8,69.6 L331.6,69 L338.5,60.9 L335.2,62.1 L337,61.4 L342.4,53.9 L347.9,61.4 L349.7,62.1 L346.4,60.9 L353.3,69 L355.1,69.6 L351.8,68.5 L360.5,79 L342.4,79 L351.2,64.8 L347.9,66.3 L349.7,65.4 L356.6,54.6 L353.4,56.1 L355.2,55.3 L360.7,45.1 L366.2,55.3 L368,56.1 L364.7,54.6 L371.6,65.4 L373.5,66.3 L370.2,64.8 L379,79 L364.6,79 L372.1,63.4 L369.3,65.1 L370.8,64.2 L376.8,52.3 L374,54 L375.5,53 L380.2,41.9 L384.8,53 L386.4,54 L383.6,52.3 L389.5,64.2 L391.1,65.1 L388.3,63.4 L395.7,79 L377.8,79 L386.5,65.5 L383.2,66.9 L385,66.1 L391.9,55.8 L388.7,5
3407.3 L390.5,56.5 L395.9,46.8 L401.4,56.5 L403.2,57.3 L399.9,55.8 L406.8,66.1 L408.6,66.9 L405.4,65.5 L414.1,79 L406.1,79 L414.8,62.4 L411.5,64.2 L413.3,63.2 L420.2,50.5 L416.9,52.3 L418.7,51.3 L424.2,39.4 L429.6,51.3 L431.4,52.3 L428.1,50.5 L435,63.2 L436.8,64.2 L433.6,62.4 L442.3,79 L425.5,79 L432.6,59.6 L429.9,61.7 L431.4,60.5 L437,45.8 L434.3,47.8 L435.8,46.7 L440.2,32.8 L444.6,46.7 L446.1,47.8 L443.5,45.8 L449.1,60.5 L450.5,61.7 L447.9,59.6 L455,79 L436.5,79 L445.2,58.8 L442,61 L443.8,59.8 L450.7,44.4 L447.4,46.6 L449.2,45.4 L454.6,31 L460.1,45.4 L461.9,46.6 L458.6,44.4 L465.5,59.8 L467.3,61 L464.1,58.8 L472.7,79 L459.8,79 L468.5,62.5 L465.2,64.3 L467.1,63.3 L474,50.8 L470.7,52.5 L472.5,51.6 L478,39.8 L483.5,51.6 L485.3,52.5 L482,50.8 L489,63.3 L490.8,64.3 L487.5,62.5 L496.3,79 L476.3,79 L486.2,62 L482.5,63.8 L484.5,62.8 L492.3,49.8 L488.6,51.6 L490.7,50.6 L496.8,38.5 L503,50.6 L505.1,51.6 L501.4,49.8 L509.2,62.8 L511.2,63.8 L507.5,62 L517.4,79 L500.6,79 L508.7,55.4 L505.7,57.9 L507.4,56.5 L513.8,38.6 L510.7,41.1 L512.4,39.7 L517.5,22.8 L522.6,39.7 L524.3,41.1 L521.3,38.6 L527.7,56.5 L529.4,57.9 L526.4,55.4 L534.5,79 L520.4,79 L529.7,58.9 L526.2,61 L528.1,59.8 L535.5,44.5 L532,46.7 L533.9,45.5 L539.7,31.1 L545.5,45.5 L547.4,46.7 L544,44.5 L551.3,59.8 L553.2,61 L549.7,58.9 L559,79 L544.2,79 L554.6,60.4 L550.7,62.4 L552.8,61.3 L561,47.1 L557.1,49.1 L559.3,48 L565.8,34.8 L572.3,48 L574.4,49.1 L570.5,47.1 L578.7,61.3 L580.9,62.4 L577,60.4 L587.4,79 L568.9,79 L577.2,61.8 L574.1,63.6 L575.9,62.6 L582.5,49.5 L579.3,51.3 L581.1,50.3 L586.3,38 L591.5,50.3 L593.2,51.3 L590.1,49.5 L596.7,62.6 L598.4,63.6 L595.3,61.8 L603.6,79 L596,79 L604,60.5 L601,62.5 L602.7,61.4 L609.1,47.3 L606,49.3 L607.7,48.2 L612.8,35 L617.8,48.2 L619.5,49.3 L616.5,47.3 L622.9,61.4 L624.5,62.5 L621.5,60.5 L629.6,79 L616.2,79 L622.6,60.8 L620.2,62.8 L621.5,61.7 L626.6,47.9 L624.2,49.8 L625.6,48.7 L629.6,35.8 L633.6,48.7 L634.9,49.8 L632.5,47.9 L637.6,61.7 L638.9,62.8 L636.5,60.8 L642.9,79 L635,79 L642.3,54.4 L639.6,57 L641.1,55.5 L646.9,36.8 L644.2,39.4 L645.7,37.9 L650.3,20.3 L654.9,37.9 L656.5,39.4 L653.7,36.8 L659.5,55.5 L661.1,57 L658.3,54.4 L665.7,79 L653.1,79 L663.1,57.7 L659.3,59.9 L661.4,58.7 L669.3,42.4 L665.6,44.7 L667.7,43.4 L673.9,28.2 L680.1,43.4 L682.2,44.7 L678.5,42.4 L686.4,58.7 L688.4,59.9 L684.7,57.7 L694.7,79 L676.6,79 L686.4,62.9 L682.7,64.7 L684.8,63.7 L692.5,51.5 L688.8,53.2 L690.9,52.2 L697,40.8 L703.2,52.2 L705.2,53.2 L701.5,51.5 L709.3,63.7 L711.3,64.7 L707.7,62.9 L717.5,79 L710.9,79 L717.4,57.5 L714.9,59.8 L716.3,58.5 L721.4,42.1 L719,44.4 L720.3,43.1 L724.4,27.7 L728.4,43.1 L729.8,44.4 L727.4,42.1 L732.5,58.5 L733.8,59.8 L731.4,57.5 L737.9,79 L727.2,79 L734.2,60.5 L731.6,62.5 L733,61.4 L738.6,47.4 L735.9,49.3 L737.4,48.2 L741.8,35 L746.1,48.2 L747.6,49.3 L745,47.4 L750.5,61.4 L752,62.5 L749.4,60.5 L756.4,79 L744.7,79 L752.5,66 L749.6,67.4 L751.2,66.6 L757.4,56.7 L754.4,58.1 L756.1,57.3 L761,48.1 L765.8,57.3 L767.5,58.1 L764.5,56.7 L770.7,66.6 L772.4,67.4 L769.4,66 L777.3,79 L761.1,79 L767.3,62.7 L764.9,64.4 L766.2,63.4 L771.2,51 L768.8,52.8 L770.1,51.8 L774,40.1 L777.9,51.8 L779.2,52.8 L776.9,51 L781.8,63.4 L783.1,64.4 L780.7,62.7 L787,79 L774.5,79 L784.3,64.2 L780.6,65.8 L782.7,64.9 L790.5,53.7 L786.8,55.2 L788.9,54.4 L795,43.8 L801.2,54.4 L803.2,55.2 L799.5,53.7 L807.3,64.9 L809.4,65.8 L805.7,64.2 L815.6,79 L800.6,79 L809.3,64.7 L806,66.3 L807.9,65.4 L814.8,54.5 L811.5,56.1 L813.3,55.2 L818.8,45 L824.3,55.2 L826.1,56.1 L822.8,54.5 L829.8,65.4 L831.6,66.3 L828.3,64.7 L837.1,79 L821.9,79 L830.9,69 L827.5,70.1 L829.4,69.5 L836.4,61.9 L833.1,63 L834.9,62.4 L840.5,55.3 L846.1,62.4 L847.9,63 L844.6,61.9 L851.6,69.5 L853.5,70.1 L850.2,69 L859.1,79 L842.5,79 L848.7,67.7 L846.4,68.9 L847.7,68.2 L852.6,59.6 L850.3,60.8 L851.6,60.2 L855.5,52.1 L859.4,60.2 L860.7,60.8 L858.3,59.6 L863.2,68.2 L864.5,68.9 L862.2,67.7 L868.4,79 L859.8,79 L866.7,69.3 L864.1,70.3 L865.6,69.8 L871.1,62.4 L868.5,63.4 L869.9,62.8 L874.3,55.9 L878.6,62.8 L880.1,63.4 L877.5,62.4 L883,69.8 L884.4,70.3 L881.8,69.3 L888.8,79 L874.9,79 L883.8,70.1 L880.5,71.1 L882.3,70.5 L889.4,63.8 L886,64.7 L887.9,64.2 L893.5,57.9 L899,64.2 L900.9,64.7 L897.6,63.8 L904.6,70.5 L906.5,71.1 L903.1,70.1 L912.1,79 L893.5,79 L902.7,69.3 L899.2,70.3 L901.1,69.7 L908.4,62.3 L905,63.4 L906.9,62.8 L912.6,55.9 L918.3,62.8 L920.3,63.4 L916.8,62.3 L924.1,69.7 L926,70.3 L922.6,69.3 L931.7,79 L922.3,79 L931.6,70.8 L928.1,71.7 L930,71.2 L937.4,65 L933.9,65.9 L935.9,65.4 L941.7,59.5 L947.5,65.4 L949.5,65.9 L946,65 L953.3,71.2 L955.3,71.7 L951.8,70.8 L961.1,79 L943.5,79 L952.5,71 L949.1,71.8 L951,71.4 L958.1,65.2 L954.7,66.1 L956.6,65.6 L962.2,59.9 L967.8,65.6 L969.7,66.1 L966.3,65.2 L973.4,71.4 L975.3,71.8 L971.9,71 L980.9,79 L968.6,79 L975.8,71.9 L973.1,72.7 L974.6,72.2 L980.2,66.8 L977.6,67.6 L979,67.2 L983.5,62.1 L988,67.2 L989.5,67.6 L986.8,66.8 L992.4,72.2 L993.9,72.7 L991.2,71.9 L998.4,79 L989.8,79 L997.2,71.4 L994.4,72.2 L996,71.8 L1001.9,66 L999.1,66.8 L1000.6,66.3 L1005.3,60.9 L1009.9,66.3 L1011.4,66.8 L1008.7,66 L1014.5,71.8 L1016.1,72.2 L1013.3,71.4 L1020.7,79 L1009.4,79 L1017.4,70.8 L1014.4,71.7 L1016.1,71.2 L1022.5,65 L1019.4,65.9 L1021.1,65.4 L1026.2,59.6 L1031.2,65.4 L1032.9,65.9 L1029.9,65 L1036.2,71.2 L1037.9,71.7 L1034.9,70.8 L1043,79 L1036.7,79 L1043.4,71.5 L1040.8,72.3 L1042.2,71.9 L1047.5,66.1 L1045,67 L1046.4,66.5 L1050.6,61.2 L10
34054.8,66.5 L1056.2,67 L1053.7,66.1 L1059,71.9 L1060.4,72.3 L1057.9,71.5 L1064.6,79 L1057,79 L1065.9,71.8 L1062.6,72.5 L1064.4,72.1 L1071.4,66.6 L1068.1,67.4 L1070,66.9 L1075.5,61.8 L1081,66.9 L1082.9,67.4 L1079.6,66.6 L1086.6,72.1 L1088.4,72.5 L1085.1,71.8 L1093.9,79 L1076.4,79 L1083.2,71.4 L1080.7,72.2 L1082.1,71.8 L1087.5,66 L1084.9,66.8 L1086.4,66.3 L1090.6,60.9 L1094.9,66.3 L1096.3,66.8 L1093.8,66 L1099.2,71.8 L1100.6,72.2 L1098,71.4 L1104.8,79 L1089,79 L1096.6,68.6 L1093.7,69.7 L1095.3,69.1 L1101.3,61.2 L1098.5,62.3 L1100,61.7 L1104.8,54.2 L1109.5,61.7 L1111.1,62.3 L1108.3,61.2 L1114.3,69.1 L1115.8,69.7 L1113,68.6 L1120.6,79 L1109.3,79 L1117.8,68.9 L1114.6,70 L1116.4,69.4 L1123.2,61.7 L1120,62.8 L1121.7,62.2 L1127.1,55 L1132.4,62.2 L1134.2,62.8 L1131,61.7 L1137.7,69.4 L1139.5,70 L1136.3,68.9 L1144.8,79 L1132.4,79 L1142.5,69 L1138.7,70.1 L1140.9,69.5 L1148.9,61.9 L1145.1,62.9 L1147.2,62.3 L1153.5,55.2 L1159.9,62.3 L1162,62.9 L1158.2,61.9 L1166.2,69.5 L1168.3,70.1 L1164.5,69 L1174.6,79 L1156.4,79 L1166.5,69 L1162.7,70.1 L1164.8,69.5 L1172.9,61.9 L1169.1,63 L1171.2,62.4 L1177.6,55.3 L1183.9,62.4 L1186,63 L1182.2,61.9 L1190.3,69.5 L1192.4,70.1 L1188.6,69 L1198.8,79 L1183.5,79 L1189.9,65.7 L1187.5,67.1 L1188.8,66.3 L1193.9,56.2 L1191.5,57.6 L1192.9,56.8 L1196.9,47.3 L1200.9,56.8 L1202.3,57.6 L1199.9,56.2 L1205,66.3 L1206.3,67.1 L1203.9,65.7 L1210.3,79 L1196.2,79 L1206.4,65.3 L1202.6,66.8 L1204.7,66 L1212.7,55.6 L1208.9,57.1 L1211,56.2 L1217.3,46.5 L1223.6,56.2 L1225.8,57.1 L1222,55.6 L1230,66 L1232.1,66.8 L1228.3,65.3 L1238.4,79 L1210,79 L1210,90 Z" fill="currentColor" fill-opacity="0.45"></path><path d="M-10,90 L-10,78 L-14.1,78 L-7.7,70.4 L-10.1,71.2 L-8.8,70.8 L-3.7,65 L-6.1,65.8 L-4.8,65.3 L-0.8,59.9 L3.2,65.3 L4.5,65.8 L2.2,65 L7.2,70.8 L8.5,71.2 L6.1,70.4 L12.5,78 L0.6,78 L7,69.2 L4.6,70.2 L5.9,69.6 L11,63 L8.6,63.9 L10,63.4 L14,57.1 L18,63.4 L19.3,63.9 L16.9,63 L22,69.6 L23.3,70.2 L20.9,69.2 L27.3,78 L17.5,78 L23.5,69.9 L21.3,70.8 L22.5,70.3 L27.3,64.2 L25,65 L26.3,64.5 L30,58.8 L33.8,64.5 L35,65 L32.8,64.2 L37.5,70.3 L38.8,70.8 L36.5,69.9 L42.5,78 L35.2,78 L42.2,70.3 L39.6,71.1 L41.1,70.7 L46.7,64.8 L44,65.7 L45.5,65.2 L49.9,59.7 L54.3,65.2 L55.8,65.7 L53.1,64.8 L58.7,70.7 L60.2,71.1 L57.5,70.3 L64.6,78 L52,78 L57.1,70.9 L55.2,71.7 L56.3,71.3 L60.4,65.9 L58.4,66.6 L59.5,66.2 L62.7,61.2 L66,66.2 L67,66.6 L65.1,65.9 L69.2,71.3 L70.3,71.7 L68.3,70.9 L73.5,78 L65.5,78 L70,68.9 L68.3,69.9 L69.2,69.4 L72.8,62.5 L71.1,63.4 L72,62.9 L74.8,56.4 L77.6,62.9 L78.5,63.4 L76.9,62.5 L80.4,69.4 L81.3,69.9 L79.6,68.9 L84.1,78 L75.7,78 L83.6,69.3 L80.6,70.2 L82.3,69.7 L88.5,63 L85.6,63.9 L87.2,63.4 L92.2,57.2 L97.1,63.4 L98.7,63.9 L95.8,63 L102,69.7 L103.7,70.2 L100.7,69.3 L108.6,78 L98,78 L104.8,68.9 L102.2,69.8 L103.7,69.3 L109.1,62.3 L106.5,63.3 L107.9,62.8 L112.2,56.2 L116.5,62.8 L117.9,63.3 L115.3,62.3 L120.7,69.3 L122.2,69.8 L119.6,68.9 L126.4,78 L108.7,78 L117.3,65.8 L114.1,67.1 L115.8,66.4 L122.6,57.1 L119.4,58.4 L121.2,57.7 L126.5,49 L131.8,57.7 L133.6,58.4 L130.4,57.1 L137.2,66.4 L138.9,67.1 L135.7,65.8 L144.3,78 L130.4,78 L135.9,64.7 L133.9,66.2 L135,65.4 L139.4,55.3 L137.3,56.7 L138.5,55.9 L141.9,46.4 L145.4,55.9 L146.5,56.7 L144.4,55.3 L148.8,65.4 L149.9,66.2 L147.9,64.7 L153.4,78 L147.3,78 L151.8,63 L150.1,64.6 L151.1,63.7 L154.7,52.3 L153,53.9 L153.9,53 L156.7,42.3 L159.6,53 L160.5,53.9 L158.8,52.3 L162.4,63.7 L163.4,64.6 L161.7,63 L166.2,78 L159.7,78 L163.7,65.7 L162.2,67 L163,66.2 L166.2,56.8 L164.7,58.2 L165.5,57.4 L168,48.6 L170.5,57.4 L171.3,58.2 L169.8,56.8 L172.9,66.2 L173.8,67 L172.3,65.7 L176.2,78 L167.7,78 L174,64.1 L171.6,65.6 L173,64.8 L178,54.2 L175.6,55.7 L176.9,54.9 L180.9,45 L184.9,54.9 L186.2,55.7 L183.8,54.2 L188.9,64.8 L190.2,65.6 L187.8,64.1 L194.2,78 L186.6,78 L190.9,61 L189.3,62.8 L190.2,61.8 L193.6,48.8 L192,50.7 L192.8,49.6 L195.5,37.5 L198.2,49.6 L199.1,50.7 L197.5,48.8 L200.8,61.8 L201.7,62.8 L200.1,61 L204.4,78 L195.3,78 L202.2,63.2 L199.6,64.8 L201.1,63.9 L206.5,52.6 L203.9,54.2 L205.4,53.3 L209.7,42.7 L214,53.3 L215.4,54.2 L212.8,52.6 L218.3,63.9 L219.7,64.8 L217.1,63.2 L224,78 L211.7,78 L217.2,61.8 L215.1,63.5 L216.3,62.5 L220.7,50.2 L218.6,51.9 L219.7,50.9 L223.2,39.3 L226.7,50.9 L227.8,51.9 L225.7,50.2 L230.1,62.5 L231.3,63.5 L229.2,61.8 L234.7,78 L224,78 L231.5,61.5 L228.7,63.3 L230.2,62.3 L236.2,49.7 L233.4,51.5 L234.9,50.5 L239.6,38.7 L244.3,50.5 L245.8,51.5 L243,49.7 L248.9,62.3 L250.5,63.3 L247.7,61.5 L255.2,78 L240.9,78 L248.8,61.4 L245.9,63.2 L247.5,62.2 L253.7,49.5 L250.8,51.3 L252.4,50.3 L257.3,38.4 L262.3,50.3 L263.9,51.3 L261,49.5 L267.2,62.2 L268.8,63.2 L265.9,61.4 L273.8,78 L256.6,78 L263.4,56.9 L260.8,59.2 L262.3,58 L267.7,41.9 L265.1,44.2 L266.5,42.9 L270.8,27.9 L275.1,42.9 L276.5,44.2 L273.9,41.9 L279.3,58 L280.8,59.2 L278.2,56.9 L285,78 L273.9,78 L282.2,59.6 L279.1,61.6 L280.8,60.5 L287.4,46.4 L284.3,48.4 L286,47.3 L291.2,34.2 L296.4,47.3 L298.2,48.4 L295.1,46.4 L301.7,60.5 L303.4,61.6 L300.3,59.6 L308.6,78 L297.1,78 L305.3,58 L302.2,60.2 L303.9,59 L310.5,43.8 L307.4,45.9 L309.1,44.7 L314.3,30.4 L319.4,44.7 L321.1,45.9 L318,43.8 L324.6,59 L326.3,60.2 L323.2,58 L331.4,78 L316.9,78 L323.3,58.8 L320.9,60.9 L322.2,59.7 L327.2,45.1 L324.8,47.2 L326.2,46.1 L330.1,32.4 L334,46.1 L335.4,47.2 L333,45.1 L338,59.7 L339.3,60.9 L336.9,58.8 L343.2,78 L334.5,78 L340.3,58.5 L338.1,60.6 L339.3,59.4 L343.9,44.5 L341.8,46.6 L343,45.5 L346.6,31.5 L350.2,45.5 L351.4,46.6 L349.3,44.5 L353.8,59.4 L355.1,60.6 L352.9,58.5 L358.7,78 L345.9,78 L352.4,51.1 L350,53.9 L351.3,52.3 L356.4,31.8 L354,34.7 L355.3,33.1 L359.4,13.9 L363.4,33.1 L364.7,34.7 L362.3,31.8 L367.4,52.3 L368.8,53.9 L366.4,51.1 L372.8,78 L361.3,78 L368.1,53.7 L365.5,56.3 L366.9,54.9 L372.3,36.4 L369.8,39 L371.2,37.6 L375.5,20.2 L379.7,37.6 L381.2,39 L378.6,36.4 L384,54.9 L385.4,56.3 L382.9,53.7 L389.7,78 L382.8,78 L389.5,52.8 L387,55.5 L388.4,54 L393.7,34.7 L391.2,37.4 L392.6,35.9 L396.8,17.9 L401,35.9 L402.4,37.4 L399.9,34.7 L405.2,54 L406.6,55.5 L404.1,52.8 L410.9,78 L400.5,78 L407.5,61.1 L404.9,62.9 L406.3,61.9 L411.8,49.1 L409.2,50.9 L410.7,49.9 L415,37.8 L419.4,49.9 L420.8,50.9 L418.2,49.1 L423.7,61.9 L425.2,62.9 L422.6,61.1 L429.6,78 L423.5,78 L428,50.9 L426.3,53.8 L427.2,52.2 L430.8,31.6 L429.1,34.5 L430,32.8 L432.8,13.5 L435.6,32.8 L436.6,34.5 L434.9,31.6 L438.4,52.2 L439.4,53.8 L437.7,50.9 L442.2,78 L436.6,78 L442.1,46.7 L440,50.1 L441.2,48.2 L445.5,24.4 L443.5,27.7 L444.6,25.9 L448,3.6 L451.5,25.9 L452.6,27.7 L450.5,24.4 L454.9,48.2 L456,50.1 L454,46.7 L459.5,78 L445.8,78 L452.8,50.6 L450.1,53.5 L451.6,51.9 L457.1,31 L454.5,33.9 L456,32.3 L460.3,12.7 L464.7,32.3 L466.1,33.9 L463.5,31 L469,51.9 L470.5,53.5 L467.9,50.6 L474.9,78 L463.4,78 L469.6,52.6 L467.2,55.3 L468.5,53.8 L473.4,34.4 L471.1,37.1 L472.4,35.6 L476.3,17.4 L480.2,35.6 L481.4,37.1 L479.1,34.4 L484,53.8 L485.3,55.3 L483,52.6 L489.2,78 L476.3,78 L481.7,52.2 L479.6,55 L480.8,53.5 L485,33.8 L483,36.6 L484.1,35 L487.5,16.6 L490.8,35 L491.9,36.6 L489.9,33.8 L494.1,53.5 L495.3,55 L493.2,52.2 L498.6,78 L492.2,78 L496.9,57.9 L495.1,60.1 L496.1,58.9 L499.9,43.6 L498.1,45.7 L499.1,44.5 L502,30.2 L505,44.5 L505.9,45.7 L504.2,43.6 L507.9,58.9 L508.9,60.1 L507.1,57.9 L511.8,78 L507.2,78 L511.1,53 L509.6,55.7 L510.5,54.2 L513.5,35.2 L512.1,37.9 L512.9,36.4 L515.3,18.6 L517.7,36.4 L518.5,37.9 L517.1,35.2 L520.1,54.2 L520.9,5
3405.7 L519.5,53 L523.3,78 L515.9,78 L523.1,56.3 L520.4,58.6 L521.9,57.3 L527.6,40.7 L524.9,43.1 L526.4,41.8 L530.9,26.3 L535.4,41.8 L536.9,43.1 L534.2,40.7 L539.9,57.3 L541.4,58.6 L538.7,56.3 L545.9,78 L529.5,78 L535.7,58.1 L533.4,60.2 L534.7,59 L539.6,43.8 L537.3,46 L538.5,44.8 L542.4,30.5 L546.3,44.8 L547.6,46 L545.3,43.8 L550.2,59 L551.5,60.2 L549.1,58.1 L555.3,78 L551.3,78 L555.5,64.6 L554,66 L554.8,65.2 L558.2,55 L556.6,56.4 L557.5,55.6 L560.1,46 L562.8,55.6 L563.7,56.4 L562.1,55 L565.5,65.2 L566.3,66 L564.7,64.6 L569,78 L561.7,78 L569.5,57.1 L566.6,59.4 L568.2,58.1 L574.4,42.2 L571.5,44.5 L573.1,43.2 L578,28.3 L582.9,43.2 L584.6,44.5 L581.6,42.2 L587.8,58.1 L589.5,59.4 L586.5,57.1 L594.4,78 L589.7,78 L594.4,66.2 L592.6,67.5 L593.6,66.8 L597.3,57.8 L595.6,59.1 L596.5,58.4 L599.4,49.9 L602.3,58.4 L603.3,59.1 L601.6,57.8 L605.2,66.8 L606.2,67.5 L604.5,66.2 L609.1,78 L596.8,78 L603.2,62.9 L600.8,64.5 L602.2,63.6 L607.2,52 L604.8,53.7 L606.2,52.8 L610.2,41.9 L614.2,52.8 L615.5,53.7 L613.1,52 L618.2,63.6 L619.5,64.5 L617.1,62.9 L623.5,78 L610.9,78 L616,63 L614.1,64.6 L615.2,63.7 L619.2,52.3 L617.3,53.9 L618.4,53 L621.6,42.4 L624.8,53 L625.9,53.9 L624,52.3 L628,63.7 L629.1,64.6 L627.2,63 L632.3,78 L625.4,78 L630.9,64.3 L628.8,65.8 L630,65 L634.3,54.5 L632.2,56 L633.4,55.2 L636.8,45.4 L640.2,55.2 L641.3,56 L639.3,54.5 L643.6,65 L644.8,65.8 L642.7,64.3 L648.2,78 L638.5,78 L643.8,60.3 L641.8,62.2 L642.9,61.2 L647.1,47.7 L645.1,49.6 L646.2,48.6 L649.5,36 L652.8,48.6 L653.9,49.6 L651.9,47.7 L656.1,61.2 L657.2,62.2 L655.2,60.3 L660.5,78 L650.6,78 L656,63.6 L653.9,65.1 L655.1,64.3 L659.3,53.3 L657.3,54.9 L658.4,54 L661.8,43.7 L665.1,54 L666.2,54.9 L664.2,53.3 L668.5,64.3 L669.6,65.1 L667.6,63.6 L672.9,78 L664.8,78 L669.3,69.4 L667.6,70.4 L668.6,69.9 L672.1,63.3 L670.4,64.3 L671.4,63.7 L674.2,57.6 L676.9,63.7 L677.9,64.3 L676.2,63.3 L679.7,69.9 L680.7,70.4 L679,69.4 L683.5,78 L672.5,78 L680.2,68.9 L677.3,69.9 L678.9,69.4 L685.1,62.5 L682.2,63.5 L683.8,62.9 L688.6,56.4 L693.5,62.9 L695.1,63.5 L692.2,62.5 L698.4,69.4 L700,69.9 L697.1,68.9 L704.8,78 L695.8,78 L703.2,65.6 L700.4,66.9 L701.9,66.2 L707.8,56.8 L705,58.1 L706.5,57.3 L711.2,48.5 L715.8,57.3 L717.3,58.1 L714.5,56.8 L720.4,66.2 L721.9,66.9 L719.2,65.6 L726.6,78 L709.5,78 L716.9,70.4 L714.1,71.2 L715.6,70.8 L721.5,65 L718.7,65.8 L720.3,65.3 L724.9,59.9 L729.5,65.3 L731.1,65.8 L728.3,65 L734.2,70.8 L735.7,71.2 L732.9,70.4 L740.3,78 L729.7,78 L734,69.6 L732.4,70.5 L733.3,70 L736.7,63.6 L735.1,64.5 L736,64 L738.7,57.9 L741.4,64 L742.3,64.5 L740.6,63.6 L744.1,70 L744.9,70.5 L743.3,69.6 L747.6,78 L740.4,78 L747,68.3 L744.5,69.4 L745.9,68.8 L751.1,61.4 L748.6,62.5 L750,61.9 L754.2,55 L758.3,61.9 L759.7,62.5 L757.2,61.4 L762.4,68.8 L763.8,69.4 L761.3,68.3 L767.9,78 L756.2,78 L763.7,70.3 L760.9,71.1 L762.4,70.7 L768.4,64.8 L765.6,65.6 L767.1,65.1 L771.8,59.6 L776.5,65.1 L778.1,65.6 L775.3,64.8 L781.2,70.7 L782.8,71.1 L780,70.3 L787.5,78 L770.7,78 L777.5,71.4 L775,72.1 L776.4,71.8 L781.8,66.8 L779.2,67.5 L780.7,67.1 L784.9,62.4 L789.2,67.1 L790.6,67.5 L788.1,66.8 L793.5,71.8 L794.9,72.1 L792.4,71.4 L799.2,78 L787.6,78 L795.6,68.7 L792.6,69.7 L794.2,69.2 L800.6,62.1 L797.6,63.1 L799.2,62.6 L804.2,55.9 L809.2,62.6 L810.9,63.1 L807.9,62.1 L814.2,69.2 L815.9,69.7 L812.9,68.7 L820.9,78 L814.5,78 L820.9,71.9 L818.5,72.6 L819.9,72.2 L824.9,67.6 L822.5,68.2 L823.8,67.9 L827.8,63.5 L831.8,67.9 L833.1,68.2 L830.7,67.6 L835.8,72.2 L837.1,72.6 L834.7,71.9 L841.1,78 L832.4,78 L836.9,68.7 L835.2,69.7 L836.1,69.1 L839.7,62 L838,63 L838.9,62.5 L841.8,55.8 L844.6,62.5 L845.5,63 L843.8,62 L847.4,69.1 L848.3,69.7 L846.6,68.7 L851.1,78 L838.7,78 L847.3,68.7 L844,69.7 L845.8,69.1 L852.6,62 L849.4,63 L851.2,62.5 L856.6,55.8 L861.9,62.5 L863.7,63 L860.5,62 L867.3,69.1 L869.1,69.7 L865.9,68.7 L874.5,78 L863.6,78 L867.9,70 L866.3,70.9 L867.2,70.4 L870.6,64.3 L869,65.2 L869.9,64.7 L872.6,59 L875.3,64.7 L876.2,65.2 L874.5,64.3 L877.9,70.4 L878.8,70.9 L877.2,70 L881.5,78 L868.7,78 L877.1,71.3 L873.9,72 L875.7,71.6 L882.3,66.4 L879.2,67.2 L880.9,66.8 L886.1,61.9 L891.3,66.8 L893.1,67.2 L889.9,66.4 L896.5,71.6 L898.3,72 L895.1,71.3 L903.5,78 L887.8,78 L896.1,70.1 L893,71 L894.7,70.5 L901.3,64.5 L898.2,65.3 L899.9,64.8 L905.1,59.2 L910.3,64.8 L912.1,65.3 L908.9,64.5 L915.5,70.5 L917.3,71 L914.1,70.1 L922.5,78 L916.4,78 L920.5,69.2 L919,70.1 L919.8,69.6 L923.1,62.9 L921.6,63.9 L922.4,63.3 L925,57.1 L927.6,63.3 L928.5,63.9 L926.9,62.9 L930.2,69.6 L931,70.1 L929.5,69.2 L933.6,78 L923.1,78 L928.7,69.6 L926.6,70.5 
340L927.8,70 L932.3,63.6 L930.1,64.5 L931.3,64 L934.8,58 L938.4,64 L939.5,64.5 L937.4,63.6 L941.9,70 L943,70.5 L940.9,69.6 L946.6,78 L942.1,78 L948.1,66.2 L945.9,67.5 L947.1,66.8 L951.9,57.8 L949.6,59.1 L950.9,58.4 L954.7,50 L958.5,58.4 L959.7,59.1 L957.5,57.8 L962.2,66.8 L963.5,67.5 L961.2,66.2 L967.3,78 L954.8,78 L961.2,65.3 L958.8,66.7 L960.1,65.9 L965.2,56.3 L962.8,57.7 L964.2,56.9 L968.2,47.9 L972.2,56.9 L973.6,57.7 L971.2,56.3 L976.3,65.9 L977.6,66.7 L975.2,65.3 L981.6,78 L972.3,78 L977.6,61.4 L975.6,63.2 L976.7,62.2 L980.9,49.6 L979,51.4 L980.1,50.4 L983.4,38.6 L986.7,50.4 L987.8,51.4 L985.8,49.6 L990,62.2 L991.1,63.2 L989.1,61.4 L994.4,78 L986.1,78 L991.1,67.4 L989.3,68.5 L990.3,67.9 L994.2,59.8 L992.4,60.9 L993.4,60.3 L996.5,52.7 L999.6,60.3 L1000.7,60.9 L998.8,59.8 L1002.7,67.9 L1003.8,68.5 L1001.9,67.4 L1006.9,78 L991.5,78 L998.9,67.3 L996.1,68.4 L997.7,67.8 L1003.5,59.6 L1000.7,60.8 L1002.3,60.1 L1006.9,52.4 L1011.5,60.1 L1013.1,60.8 L1010.3,59.6 L1016.2,67.8 L1017.7,68.4 L1014.9,67.3 L1022.3,78 L1008.4,78 L1016,63.3 L1013.1,64.9 L1014.7,64 L1020.7,52.9 L1017.9,54.4 L1019.5,53.6 L1024.2,43.1 L1029,53.6 L1030.5,54.4 L1027.7,52.9 L1033.7,64 L1035.3,64.9 L1032.4,63.3 L1040,78 L1031.9,78 L1037.6,59.5 L1035.5,61.4 L1036.6,60.3 L1041.1,46.2 L1039,48.2 L1040.2,47.1 L1043.7,33.9 L1047.2,47.1 L1048.4,48.2 L1046.3,46.2 L1050.8,60.3 L1051.9,61.4 L1049.8,59.5 L1055.5,78 L1044.9,78 L1052.2,62.3 L1049.4,64 L1051,63 L1056.7,51.1 L1054,52.7 L1055.5,51.8 L1060,40.6 L1064.6,51.8 L1066.1,52.7 L1063.3,51.1 L1069.1,63 L1070.6,64 L1067.9,62.3 L1075.1,78 L1058.1,78 L1065.2,59.2 L1062.6,61.2 L1064.1,60.1 L1069.7,45.8 L1067,47.8 L1068.5,46.7 L1072.9,33.3 L1077.4,46.7 L1078.9,47.8 L1076.2,45.8 L1081.8,60.1 L1083.3,61.2 L1080.7,59.2 L1087.8,78 L1083.9,78 L1088.4,52.9 L1086.7,55.6 L1087.7,54.1 L1091.2,35 L1089.5,37.7 L1090.5,36.2 L1093.3,18.3 L1096.1,36.2 L1097,37.7 L1095.3,35 L1098.9,54.1 L1099.8,55.6 L1098.1,52.9 L1102.6,78 L1094.1,78 L1100.7,54.8 L1098.3,57.3 L1099.6,55.9 L1104.8,38.3 L1102.4,40.8 L1103.7,39.4 L1107.8,22.8 L1112,39.4 L1113.3,40.8 L1110.9,38.3 L1116.1,55.9 L1117.4,57.3 L1115,54.8 L1121.5,78 L1115.4,78 L1120.4,57.6 L1118.5,59.8 L1119.5,58.5 L1123.4,43 L1121.6,45.2 L1122.6,43.9 L1125.7,29.3 L1128.8,43.9 L1129.8,45.2 L1127.9,43 L1131.8,58.5 L1132.9,59.8 L1131,57.6 L1135.9,78 L1130.8,78 L1134.9,53.1 L1133.4,55.7 L1134.2,54.3 L1137.4,35.3 L1135.9,37.9 L1136.8,36.5 L1139.3,18.7 L1141.9,36.5 L1142.7,37.9 L1141.2,35.3 L1144.4,54.3 L1145.3,55.7 L1143.7,53.1 L1147.8,78 L1135.5,78 L1143,56.9 L1140.2,59.2 L1141.7,57.9 L1147.6,41.9 L1144.8,44.2 L1146.4,42.9 L1151,27.9 L1155.7,42.9 L1157.3,44.2 L1154.5,41.9 L1160.4,57.9 L1161.9,59.2 L1159.1,56.9 L1166.6,78 L1160.1,78 L1164.5,51.2 L1162.8,54.1 L1163.8,52.5 L1167.3,32.1 L1165.6,35 L1166.5,33.4 L1169.3,14.3 L1172.1,33.4 L1173,35 L1171.3,32.1 L1174.8,52.5 L1175.8,54.1 L1174.1,51.2 L1178.5,78 L1163.9,78 L1172.2,62.8 L1169.1,64.4 L1170.8,63.5 L1177.5,51.9 L1174.3,53.6 L1176.1,52.6 L1181.3,41.8 L1186.5,52.6 L1188.3,53.6 L1185.1,51.9 L1191.7,63.5 L1193.5,64.4 L1190.4,62.8 L1198.7,78 L1190.7,78 L1196.1,58 L1194.1,60.1 L1195.2,58.9 L1199.5,43.7 L1197.5,45.8 L1198.6,44.6 L1202,30.3 L1205.3,44.6 L1206.4,45.8 L1204.4,43.7 L1208.7,58.9 L1209.8,60.1 L1207.8,58 L1213.2,78 L1210,78 L1210,90 Z" fill="currentColor"></path></svg></div><div class="relative flex flex-col text-white px-16 pb-16 pt-8 justify-center items-center text-center" style="background:#71222f"><canvas aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full"></canvas><svg aria-hidden="true" class="absolute right-[8%] top-10 hidden -rotate-6 lg:block" height="88" viewBox="0 0 96 96" width="88"><defs><path d="M 15 48 A 33 33 0 0 1 81 48 A 33 33 0 0 1 15 48" id="ranger-badge-footer-top"></path><path d="M 16 48 A 32 32 0 0 0 80 48 A 32 32 0 0 0 16 48" id="ranger-badge-footer-bottom"></path></defs><circle cx="48" cy="48" fill="none" r="45" stroke="rgba(255, 240, 220, 0.75)" stroke-dasharray="2 3" stroke-width="1.5"></circle><circle cx="48" cy="48" fill="none" r="22" stroke="rgba(255, 240, 220, 0.75)" stroke-width="1"></circle><text fill="rgba(255, 240, 220, 0.75)" font-family="var(--font-poppins), sans-serif" font-size="6.5" font-weight="600" letter-spacing="1.2"><textPath href="#ranger-badge-footer-top" startOffset="25%" text-anchor="middle">CHRISTOFFER ARTMANN</textPath></text><text fill="rgba(255, 240, 220, 0.75)" font-family="var(--font-poppins), sans-serif" font-size="6.5" font-weight="600" letter-spacing="1.2"><textPath href="#ranger-badge-footer-bottom" startOffset="25%" text-anchor="middle">BARCELONA · LOOKOUT</textPath></text><path d="M36 56 L44 43 L48.5 49.5 L52 45 L60 56 Z" fill="none" stroke="rgba(255, 240, 220, 0.75)" stroke-linejoin="round" stroke-width="1.5"></path><circle cx="56" cy="40" fill="none" r="2.5" stroke="rgba(255, 240, 220, 0.75)" stroke-width="1.2"></circle></svg><svg aria-hidden="true" class="absolute bottom-4 left-4 md:bottom-6 md:left-10" height="48" viewBox="0 0 64 56" width="54.857142857142854"><ellipse class="campfire-glow" cx="32" cy="44" fill="#f97316" rx="22" ry="10"></ellipse><circle class="campfire-spark" cx="26" cy="24" fill="#fbbf24" r="1"></circle><circle class="campfire-spark" cx="39" cy="28" fill="#fcd34d" r="0.8" style="animation-delay:-1.4s"></circle><g class="campfire-flame-outer">
340<path d="M32 12 C38 22 43 30 43 38 C43 45 38 49 32 49 C26 49 21 45 21 38 C21 30 26 22 32 12 Z" fill="#f59e0b"></path></g><g class="campfire-flame-mid"><path d="M32 20 C36 27 39.5 32 39.5 38 C39.5 43.5 36 46.5 32 46.5 C28 46.5 24.5 43.5 24.5 38 C24.5 32 28 27 32 20 Z" fill="#f97316"></path></g><g class="campfire-flame-inner"><path d="M32 29 C34.5 33.5 36 36.5 36 40 C36 43.5 34 45 32 45 C30 45 28 43.5 28 40 C28 36.5 29.5 33.5 32 29 Z" fill="#fde68a"></path></g><rect fill="#8a5a3b" height="5" rx="2.5" transform="rotate(14 32 48.5)" width="26" x="19" y="46"></rect><rect fill="#6f4530" height="5" rx="2.5" transform="rotate(-14 32 48.5)" width="26" x="19" y="46"></rect></svg><div class="relative z-10 flex flex-col items-center"><div class="flex-shrink-0 mb-4"><img alt="Christoffer Artmann" class="w-16 h-16 rounded-full shadow-lg md:w-24 md:h-24" src="/images/christoffer-artmann.jpg"/></div><div class="flex flex-col items-center gap-2"><h3 class="text-xl m-0 text-white">Hi, I&#x27;m Chris!</h3><p class="text-sm m-0">I&#x27;m a Software Engineer and Product Manager living in sunny Barcelona.</p><p class="text-sm m-0">If you want to chat, you can find me on all the social platforms.</p><div class="flex gap-4 mt-4 text-2xl justify-center items-center"><a href="https://github.com/artmann/"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg></a><a href="https://www.instagram.com/christofferartmann/"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg></a><a href="https://www.linkedin.com/in/chistoffer-artmann"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg></a><a href="https://twitter.com/chrisartmann"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg></a><a href="https://linktr.ee/chrisartmann"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></a></div></div></div></div></footer><!--$--><!--/$-->
340<script src="/_next/static/chunks/04hv0w2~6vxm4.js" id="_R_" async=""></script>
340<script>(self.__next_f=self.__next_f||[]).push([0])</script>
340<script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[79520,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"\"]\n3:I[18992,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"Analytics\"]\n4:\"$Sreact.suspense\"\n5:I[10901,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"PageViewTracker\"]\n6:I[39756,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\nc:I[97367,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\ne:I[97367,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\n10:I[46900,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0bl-o8y0lf_g0.css\",\"style\"]\n:HL[\"/_next/static/media/47fe1b7cd6e6ed85-s.p.0~mcdl10zdfb3.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/83afe278b6a6bb3c-s.p.0q-301v4kxxnr.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/8e6fa89aa22d24ec-s.p.0uvzar8hswo3p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/a218039a3287bcfd-s.p.17-1enzs_j91b.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/e2334d715941921e-s.p.12skym0rqknxy.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script>
340<script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"articles\",\"signing-notarizing-and-publishing-an-electron-app-for-mac-os\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"articles\",{\"children\":[[\"slug\",\"signing-notarizing-and-publishing-an-electron-app-for-mac-os\",\"d\",null],{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0bl-o8y0lf_g0.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/1539c1wk17cta.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"inter_ad991c7-module__LhgUwq__variable poppins_27c1d5ca-module__9rNIbG__variable\",\"children\":[\"$\",\"body\",null,{\"className\":\"text-gray-700 antialiased\",\"children\":[[[\"$\",\"$L2\",null,{\"src\":\"https://www.googletagmanager.com/gtag/js?id=UA-34648805-1\",\"strategy\":\"afterInteractive\"}],[\"$\",\"$L2\",null,{\"id\":\"gtag-init\",\"strategy\":\"afterInteractive\",\"dangerouslySetInnerHTML\":{\"__html\":\"\\n                  window.dataLayer = window.dataLayer || [];\\n                  function gtag(){dataLayer.push(arguments);}\\n                  gtag('js', new Date());\\n                  gtag('config', 'UA-34648805-1', { page_path: window.location.pathname });\\n                \"}}]],[\"$\",\"$L3\",null,{}],[\"$\",\"$4\",null,{\"fallback\":null,\"children\":[\"$\",\"$L5\",null,{}]}],[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[\"$L8\",[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0x7k4xycyd2~c.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$4\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{}
340,null,false,null]},null,false,\"$@b\"]},null,false,\"$@b\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lc\",null,{\"children\":\"$Ld\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Le\",null,{\"children\":[\"$\",\"$4\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lf\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$10\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0bl-o8y0lf_g0.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"vTXBrwclECRb8fQ_fSeI2\"}\n"])</script>
340<script>self.__next_f.push([1,"11:[]\nb:\"$W11\"\n"])</script>
340<script>self.__next_f.push([1,"d:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script>
340<script>self.__next_f.push([1,"12:I[9659,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0x7k4xycyd2~c.js\"],\"default\"]\n13:I[22016,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0x7k4xycyd2~c.js\"],\"\"]\n14:I[99668,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0x7k4xycyd2~c.js\"],\"default\"]\n15:I[8450,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0x7k4xycyd2~c.js\"],\"default\"]\n1a:I[27201,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\n:HL[\"/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp\",\"image\"]\n16:T70fb,"])</script>
340<script>self.__next_f.push([1,"\u003cp\u003eI shipped a macOS build of \u003ca href=\"https://github.com/Artmann/squeal\"\u003eSqueal\u003c/a\u003e, a SQL\nclient I\u0026#39;m building, and it was completely unusable. CI was green, the release\npage had a nice \u003ccode\u003e.zip\u003c/code\u003e attached, and every single person who downloaded it got\nthe same dialog:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u0026quot;Squeal.app\u0026quot; is damaged and can\u0026#39;t be opened. You should move it to the Trash.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNothing was damaged. The download was fine. That message is macOS being\nunhelpful about a code signing problem, and it took me way longer than it should\nhave to work that out, mostly because every Electron tutorial I could find stops\nat \u003ccode\u003eelectron-forge make\u003c/code\u003e and never mentions signing at all.\u003c/p\u003e\n\u003cp\u003eSo here\u0026#39;s the config I ended up with, and all the traps I walked into on the\nway.\u003c/p\u003e\n\u003cp\u003eLet\u0026#39;s start with why that error message lies to you. \u0026quot;Damaged\u0026quot; sounds like a\ncorrupt download or a bad zip, right? It isn\u0026#39;t. What it actually means is that\nGatekeeper took a look at your app\u0026#39;s code signature and decided it wasn\u0026#39;t valid.\u003c/p\u003e\n\u003cp\u003eWhen you download a file in a browser, macOS attaches a \u003ccode\u003ecom.apple.quarantine\u003c/code\u003e\nextended attribute to it, and on first launch Gatekeeper checks the signature of\nanything carrying that flag. If there\u0026#39;s no signature at all, you get the\nfriendly \u0026quot;unidentified developer\u0026quot; dialog with a right-click-to-open escape\nhatch. But if there\u0026#39;s a signature that fails validation, you get \u0026quot;damaged\u0026quot;, and\nthere\u0026#39;s no escape hatch at all.\u003c/p\u003e\n\u003cp\u003eThe good news is that you don\u0026#39;t have to guess which one you\u0026#39;re hitting. You can\nreproduce the whole thing locally in two commands. Copy your built app, mark it\nas quarantined, and ask Gatekeeper directly:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003e\u003cspan class=\"hljs-built_in\"\u003ecp\u003c/span\u003e -R out/MyApp-darwin-arm64/MyApp.app /tmp/qt.app\nxattr -w com.apple.quarantine \u003cspan class=\"hljs-string\"\u003e\u0026quot;0083;00000000;Safari;\u0026quot;\u003c/span\u003e /tmp/qt.app\nspctl --assess --\u003cspan class=\"hljs-built_in\"\u003etype\u003c/span\u003e execute --verbose /tmp/qt.app\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOn my broken build, that printed:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-text\"\u003e/tmp/qt.app: invalid Info.plist (plist or signature have been modified)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThere it is. Not a damaged download, just a signature that doesn\u0026#39;t match the\napp. And once I signed things properly, the exact same command on the exact same\nquarantined copy printed:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-text\"\u003e/tmp/qt.app: accepted\nsource=Developer ID\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eRun that against every build before you publish it.\u003c/p\u003e\n\u003cp\u003eNow here\u0026#39;s the part that genuinely surprised me, and it\u0026#39;s specific to Electron.\u003c/p\u003e\n\u003cp\u003eYou\u0026#39;d expect an app you never signed to simply have no signature, right? But\nElectron\u0026#39;s prebuilt binaries ship with an ad-hoc signature already applied, and\nthe fuses plugin destroys it. You probably use that plugin, by the way, since it\ncomes with the default template.\u003c/p\u003e\n\u003cp\u003eFuses are build-time feature flags that toggle things like \u003ccode\u003eRunAsNode\u003c/code\u003e and\n\u003ccode\u003eEnableNodeCliInspectArguments\u003c/code\u003e, and the way they work is by rewriting bytes\ninside the Electron binary. Functionally that\u0026#39;s completely fine. But flipping a\nbyte inside a signed binary invalidates its signature.\u003c/p\u003e\n\u003cp\u003eSo an unsigned Electron app isn\u0026#39;t really unsigned at all. It\u0026#39;s carrying a\nsignature that actively fails validation, which is exactly why macOS reaches for\n\u0026quot;damaged\u0026quot; instead of the much friendlier \u0026quot;unidentified developer\u0026quot;. Two perfectly\nreasonable decisions — use the fuses plugin, don\u0026#39;t bother signing while you\u0026#39;re\ndeveloping — combine into one very confusing failure.\u003c/p\u003e\n\u003cp\u003eThe fix is to sign the app for real.\u003c/p\u003e\n\u003cp\u003eLet\u0026#39;s start with the certificate. You need a paid Apple Developer Program\nmembership, and there\u0026#39;s no free path here, because notarization requires an\nApple ID attached to a real team.\u003c/p\u003e\n\u003cp\u003eOnce you\u0026#39;re in, create a \u003cstrong\u003eDeveloper ID Application\u003c/strong\u003e certificate. Not \u0026quot;Mac App\nDistribution\u0026quot;, not \u0026quot;Apple Development\u0026quot; — those are for the Mac App Store and for\nlocal testing. Developer ID is the one for apps you hand out yourself.\u003c/p\u003e\n\u003cp\u003eInstall it, then confirm your machine can actually sign with it:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003esecurity find-identity -v -p codesigning\n\u003c/code\u003e\u003c/pre\u003e\u003cpre\u003e\u003ccode class=\"hljs language-text\"\u003e1) A8A50AAB447134FA3856408FD4030C6D5A6D95E5 \u0026quot;Developer ID Application: Your Company (TEAMID)\u0026quot;\n   1 valid identities found\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIf your certificate doesn\u0026#39;t show up in that list, the private key is missing,\nand a certificate without its key can\u0026#39;t sign anything. You\u0026#39;ll need to\nre-download it using the original CSR, or generate a new one.\u003c/p\u003e\n\u003cp\u003eThat \u003ccode\u003eTEAMID\u003c/code\u003e in the parentheses is your team ID. Write it down, you\u0026#39;ll need it\na few times.\u003c/p\u003e\n\u003cp\u003eWith the certificate installed we can configure signing, which lives in\n\u003ccode\u003epackagerConfig\u003c/code\u003e in your \u003ccode\u003eforge.config.ts\u003c/code\u003e. Notice that I gate the whole thing\non an environment variable:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-typescript\"\u003e\u003cspan class=\"hljs-attr\"\u003epackagerConfig\u003c/span\u003e: {\n  \u003cspan class=\"hljs-attr\"\u003eappBundleId\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;co.example.myapp\u0026#x27;\u003c/span\u003e,\n  \u003cspan class=\"hljs-attr\"\u003eicon\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;./assets/icons/icon\u0026#x27;\u003c/span\u003e,\n  ...(process.\u003cspan class=\"hljs-property\"\u003eenv\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003eAPPLE_TEAM_ID\u003c/span\u003e \u0026amp;\u0026amp; {\n    \u003cspan class=\"hljs-attr\"\u003eosxSign\u003c/span\u003e: {\n      \u003cspan class=\"hljs-attr\"\u003eidentity\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;Developer ID Application\u0026#x27;\u003c/span\u003e,\n      \u003cspan class=\"hljs-attr\"\u003eoptionsForFile\u003c/span\u003e: \u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003e\u003cspan class=\"hljs-attr\"\u003efilePath\u003c/span\u003e: \u003cspan class=\"hljs-built_in\"\u003estring\u003c/span\u003e\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n        \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e isMainAppBundle =\n          filePath.\u003cspan class=\"hljs-title function_\"\u003eendsWith\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;.app\u0026#x27;\u003c/span\u003e) \u0026amp;\u0026amp; !filePath.\u003cspan class=\"hljs-title function_\"\u003eincludes\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e\u0026#x27;Helper\u0026#x27;\u003c/span\u003e)\n\n        \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e {\n          \u003cspan class=\"hljs-attr\"\u003ehardenedRuntime\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n          ...(isMainAppBundle \u0026amp;\u0026amp; {\n            \u003cspan class=\"hljs-attr\"\u003eentitlements\u003c/span\u003e: \u003cspan class=\"hljs-title function_\"\u003eresolve\u003c/span\u003e(\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003emeta\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003edirname\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#x27;entitlements.plist\u0026#x27;\u003c/span\u003e)\n          })\n        }\n      }\n    },\n    \u003cspan class=\"hljs-attr\"\u003eosxNotarize\u003c/span\u003e: {\n      \u003cspan class=\"hljs-attr\"\u003eappleId\u003c/span\u003e: process.\u003cspan class=\"hljs-property\"\u003eenv\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003eAPPLE_ID\u003c/span\u003e ?? \u003cspan class=\"hljs-string\"\u003e\u0026#x27;\u0026#x27;\u003c/span\u003e,\n      \u003cspan class=\"hljs-attr\"\u003eappleIdPassword\u003c/span\u003e: process.\u003cspan class=\"hljs-property\"\u003eenv\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003eAPPLE_APP_SPECIFIC_PASSWORD\u003c/span\u003e ?? \u003cspan class=\"hljs-string\"\u003e\u0026#x27;\u0026#x27;\u003c/span\u003e,\n      \u003cspan class=\"hljs-attr\"\u003eteamId\u003c/span\u003e: process.\u003cspan class=\"hljs-property\"\u003eenv\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003eAPPLE_TEAM_ID\u003c/span\u003e\n    }\n  })\n}\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThat gate on \u003ccode\u003eAPPLE_TEAM_ID\u003c/code\u003e matters more than it looks. Without it, nobody can\nbuild your app unless they have your certificate, which breaks contributors,\nforks, and 
340your own quick local builds. With the gate, \u003ccode\u003eyarn make\u003c/code\u003e works\neverywhere and signing only kicks in when the credentials are actually there.\u003c/p\u003e\n\u003cp\u003eYou\u0026#39;ll also want to set \u003ccode\u003eappBundleId\u003c/code\u003e explicitly, because the default is\n\u003ccode\u003ecom.electron.\u0026lt;name\u0026gt;\u003c/code\u003e and you really don\u0026#39;t want that out in the wild. It has to\nstay stable forever, too. Notarization and keychain access both key off it, so\nchanging it later orphans anything your app stored in the keychain.\u003c/p\u003e\n\u003cp\u003eAnd \u003ccode\u003eoptionsForFile\u003c/code\u003e runs for every single binary in the bundle, of which there\nare a lot: helper apps, frameworks, native modules. Entitlements belong on the\nmain app bundle only, while the helpers just need the hardened runtime and\nnothing else. Get this wrong and you get mysterious crashes.\u003c/p\u003e\n\u003cp\u003eNext up is the entitlements file. Notarization requires the hardened runtime,\nand the hardened runtime happily blocks a bunch of things Electron needs. Create\n\u003ccode\u003eentitlements.plist\u003c/code\u003e in your project root:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-xml\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?xml version=\u003cspan class=\"hljs-string\"\u003e\u0026quot;1.0\u0026quot;\u003c/span\u003e encoding=\u003cspan class=\"hljs-string\"\u003e\u0026quot;UTF-8\u0026quot;\u003c/span\u003e?\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-meta\"\u003e\u0026lt;!DOCTYPE \u003cspan class=\"hljs-keyword\"\u003eplist\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003ePUBLIC\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;-//Apple//DTD PLIST 1.0//EN\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eplist\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eversion\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\u0026quot;1.0\u0026quot;\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003edict\u003c/span\u003e\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003ecom.apple.security.cs.allow-jit\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etrue\u003c/span\u003e/\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003ecom.apple.security.cs.allow-unsigned-executable-memory\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etrue\u003c/span\u003e/\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003ecom.apple.security.cs.disable-library-validation\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ekey\u003c/span\u003e\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etrue\u003c/span\u003e/\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003edict\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eplist\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eEach key in there fixes something specific:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003eallow-jit\u003c/code\u003e\u003c/strong\u003e and \u003cstrong\u003e\u003ccode\u003eallow-unsigned-executable-memory\u003c/code\u003e\u003c/strong\u003e — V8 compiles\nJavaScript to machine code at runtime and then runs it, which is precisely\nwhat the hardened runtime exists to prevent, so you have to ask for an\nexception.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003edisable-library-validation\u003c/code\u003e\u003c/strong\u003e — this is the one that gets you if you have\nnative modules. Library validation refuses to load code signed by a different\nteam, so without it any \u003ccode\u003e.node\u003c/code\u003e binding fails to load and you get a runtime\ncrash in a signed build that ran perfectly well unsigned.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf your app is pure JavaScript with no native dependencies, you can try dropping\nthat third one. If you bundle anything with a native binding, keep it.\u003c/p\u003e\n\u003cp\u003eThat brings us to notarization itself, which is Apple scanning your signed app\nfor malware and issuing a ticket that says it passed. Since macOS 10.15 it\u0026#39;s\neffectively mandatory if you want people to be able to open your app at all.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003eosxNotarize\u003c/code\u003e block above handles it, but you need an \u003cstrong\u003eapp-specific\npassword\u003c/strong\u003e, because your regular Apple ID password will not work:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eGo to \u003ca href=\"https://appleid.apple.com\"\u003eappleid.apple.com\u003c/a\u003e and sign in\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSign-In and Security\u003c/strong\u003e → \u003cstrong\u003eApp-Specific Passwords\u003c/strong\u003e → \u003cstrong\u003e+\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003eName it something like \u003ccode\u003emyapp-notarization\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eCopy the \u003ccode\u003exxxx-xxxx-xxxx-xxxx\u003c/code\u003e value\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eBefore you wire this into CI, check that the credentials actually work. It takes\na few seconds and saves you a failed release:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003excrun notarytool \u003cspan class=\"hljs-built_in\"\u003ehistory\u003c/span\u003e --apple-id \u003cspan class=\"hljs-string\"\u003e\u0026quot;[email protected]\u0026quot;\u003c/span\u003e \\\n  --password \u003cspan class=\"hljs-string\"\u003e\u0026quot;xxxx-xxxx-xxxx-xxxx\u0026quot;\u003c/span\u003e --team-id TEAMID\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIf that returns a history, even an empty one, all three notarization credentials\nare correct and work together. An auth error means the password is wrong, or\nyour Apple ID doesn\u0026#39;t have the right role on the team — you need to be Account\nHolder, Admin, or App Manager.\u003c/p\u003e\n\u003cp\u003eOne thing to be aware of is that notarization adds a few minutes to every build.\nIt\u0026#39;s an upload, a queue, and a scan, so don\u0026#39;t expect it to be instant.\u003c/p\u003e\n\u003cp\u003eNow for what you actually ship. The default Forge template hands macOS users a\n\u003ccode\u003e.zip\u003c/code\u003e, which makes for a pretty poor first run. The app ends up unzipped in\nDownloads and runs from there, never making it anywhere near the Applications\nfolder.\u003c/p\u003e\n\u003cp\u003eUse a DMG for the download instead:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003eyarn add 
340-D @electron-forge/maker-dmg\n\u003c/code\u003e\u003c/pre\u003e\u003cpre\u003e\u003ccode class=\"hljs language-typescript\"\u003e\u003cspan class=\"hljs-attr\"\u003emakers\u003c/span\u003e: [\n  \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-title class_\"\u003eMakerDMG\u003c/span\u003e({ \u003cspan class=\"hljs-attr\"\u003eicon\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\u0026#x27;./assets/icons/icon.icns\u0026#x27;\u003c/span\u003e }, [\u003cspan class=\"hljs-string\"\u003e\u0026#x27;darwin\u0026#x27;\u003c/span\u003e]),\n  \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-title class_\"\u003eMakerZIP\u003c/span\u003e({}, [\u003cspan class=\"hljs-string\"\u003e\u0026#x27;darwin\u0026#x27;\u003c/span\u003e])\n]\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eTwo traps here, and I fell into both.\u003c/p\u003e\n\u003cp\u003eThe first one is that you shouldn\u0026#39;t set \u003ccode\u003ename\u003c/code\u003e on \u003ccode\u003eMakerDMG\u003c/code\u003e. With no \u003ccode\u003ename\u003c/code\u003e,\nthe maker outputs \u003ccode\u003eMyApp-\u0026lt;version\u0026gt;-\u0026lt;arch\u0026gt;.dmg\u003c/code\u003e, but set one and every\narchitecture produces the \u003cem\u003esame\u003c/em\u003e filename. Build arm64 and x64 in separate CI\njobs, upload both to the same release, and the second one quietly overwrites the\nfirst.\u003c/p\u003e\n\u003cp\u003eThe second one is to keep the ZIP, even though nothing appears to use it. This\nnearly cost me macOS auto-updates. Squirrel.Mac can\u0026#39;t read a DMG, so if you\nupdate through \u003ccode\u003eautoUpdater\u003c/code\u003e or \u003ccode\u003eupdate-electron-app\u003c/code\u003e, that zip is the only\nformat it can install. Remove the zip maker and macOS updates stop working while\nevery build stays green. \u003ccode\u003eupdate.electronjs.org\u003c/code\u003e also matches on the filename,\n\u003ccode\u003eMyApp-darwin-arm64-\u0026lt;version\u0026gt;.zip\u003c/code\u003e, to pick the right architecture.\u003c/p\u003e\n\u003cp\u003eSo: DMG for humans, ZIP for the updater.\u003c/p\u003e\n\u003cp\u003eBefore we get to CI, a quick warning about fuses. Once you learn that flipping\nthem breaks the ad-hoc signature, the fix looks pretty obvious.\n\u003ccode\u003e@electron/fuses\u003c/code\u003e has an option for exactly this, so you set it:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-typescript\"\u003e\u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-title class_\"\u003eFusesPlugin\u003c/span\u003e({\n  \u003cspan class=\"hljs-attr\"\u003eversion\u003c/span\u003e: \u003cspan class=\"hljs-title class_\"\u003eFuseVersion\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003eV1\u003c/span\u003e,\n  \u003cspan class=\"hljs-attr\"\u003eresetAdHocDarwinSignature\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e, \u003cspan class=\"hljs-comment\"\u003e// ← don\u0026#x27;t do this\u003c/span\u003e\n  ...\n})\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eDon\u0026#39;t. I did, then read the plugin\u0026#39;s source and took it straight back out.\nHere\u0026#39;s what \u003ccode\u003e@electron-forge/plugin-fuses\u003c/code\u003e is already doing for you:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eawait\u003c/span\u003e \u003cspan class=\"hljs-title function_\"\u003eflipFuses\u003c/span\u003e(pathToElectronExecutable, {\n  \u003cspan class=\"hljs-attr\"\u003eresetAdHocDarwinSignature\u003c/span\u003e:\n    !hasOSXSignConfig \u0026amp;\u0026amp; applePlatforms.\u003cspan class=\"hljs-title function_\"\u003eincludes\u003c/span\u003e(platform) \u0026amp;\u0026amp; arch === \u003cspan class=\"hljs-string\"\u003e\u0026#x27;arm64\u0026#x27;\u003c/span\u003e,\n  ...\u003cspan class=\"hljs-variable language_\"\u003ethis\u003c/span\u003e.\u003cspan class=\"hljs-property\"\u003efusesConfig\u003c/span\u003e\n})\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIt sets the flag itself, and only when there\u0026#39;s no \u003ccode\u003eosxSign\u003c/code\u003e config, which is\nexactly the unsigned-local-build case. And notice that \u003ccode\u003e...this.fusesConfig\u003c/code\u003e is\nspread \u003cem\u003eafter\u003c/em\u003e, so your value wins and overrides that logic entirely. You\u0026#39;d be\nforcing it on for signed builds too.\u003c/p\u003e\n\u003cp\u003eIt also can\u0026#39;t do what you\u0026#39;re hoping it does. The plugin runs at\n\u003ccode\u003epackageAfterCopy\u003c/code\u003e, before Electron Packager rewrites \u003ccode\u003eInfo.plist\u003c/code\u003e with your\napp\u0026#39;s name and bundle ID. So it signs, then the plist changes underneath the\nsignature, and you\u0026#39;
340re right back to an invalid signature. I confirmed this on a\nreal build, where the app still reported \u003ccode\u003eIdentifier=com.github.Electron\u003c/code\u003e and\nfailed \u003ccode\u003ecodesign --verify\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eSo leave it alone. The valid signature comes from \u003ccode\u003eosxSign\u003c/code\u003e, which runs at the\nvery end of packaging, after everything else has settled down.\u003c/p\u003e\n\u003cp\u003eSigning locally is fine for testing, but you want your releases to be\nreproducible, and that means getting your certificate onto a CI runner.\u003c/p\u003e\n\u003cp\u003eFirst, export it. In \u003cstrong\u003eKeychain Access\u003c/strong\u003e, find your Developer ID Application\ncertificate under \u003cstrong\u003elogin\u003c/strong\u003e → \u003cstrong\u003eMy Certificates\u003c/strong\u003e. Expand it and make sure\nthere\u0026#39;s a private key underneath. Then right-click → \u003cstrong\u003eExport\u003c/strong\u003e, choose\n\u003cstrong\u003ePersonal Information Exchange (.p12)\u003c/strong\u003e, and set a strong password.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/blog/keychain-developer-id-certificate.png\" alt=\"The Developer ID Application certificate expanded in Keychain Access, with its private key listed underneath\"\u003e\u003c/p\u003e\n\u003cp\u003eCheck that the export actually contains that key, because a cert-only \u003ccode\u003e.p12\u003c/code\u003e\nfails in CI in a really confusing way:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003eopenssl pkcs12 -\u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e cert.p12 -info -noout -passin pass:\u003cspan class=\"hljs-string\"\u003e\u0026#x27;YOUR_PASSWORD\u0026#x27;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eYou want to see both a \u003ccode\u003ecertBag\u003c/code\u003e and a \u003ccode\u003ePKCS8ShroudedKeyBag\u003c/code\u003e in there. Then\nbase64 it:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003e\u003cspan class=\"hljs-built_in\"\u003ebase64\u003c/span\u003e -i cert.p12 -o cert.p12.b64\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eAdd five repository secrets: \u003ccode\u003eAPPLE_CERTIFICATE\u003c/code\u003e (the base64 blob),\n\u003ccode\u003eAPPLE_CERTIFICATE_PASSWORD\u003c/code\u003e, \u003ccode\u003eAPPLE_ID\u003c/code\u003e, \u003ccode\u003eAPPLE_APP_SPECIFIC_PASSWORD\u003c/code\u003e, and\n\u003ccode\u003eAPPLE_TEAM_ID\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eOn the runner, the certificate goes into a temporary keychain:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-yaml\"\u003e\u003cspan class=\"hljs-bullet\"\u003e-\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ename:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eImport\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eApple\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ecertificate\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eif:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003estartsWith(matrix.os,\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;macos\u0026#x27;\u003c/span\u003e\u003cspan class=\"hljs-string\"\u003e)\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eenv:\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_CERTIFICATE:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_CERTIFICATE\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_CERTIFICATE_PASSWORD:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_CERTIFICATE_PASSWORD\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003erun:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e|\n    CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12\n    KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db\n    KEYCHAIN_PASSWORD=$(
340openssl rand -base64 32)\n\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-n\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;$APPLE_CERTIFICATE\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e|\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ebase64\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e--decode\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-o\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$CERTIFICATE_PATH\u003c/span\u003e\n\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ecreate-keychain\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-p\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;$KEYCHAIN_PASSWORD\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eset-keychain-settings\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-lut\u003c/span\u003e \u003cspan class=\"hljs-number\"\u003e21600\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eunlock-keychain\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-p\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;$KEYCHAIN_PASSWORD\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eimport\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$CERTIFICATE_PATH\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-P\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;$APPLE_CERTIFICATE_PASSWORD\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\\\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003e-A\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-t\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ecert\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-f\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003epkcs12\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-k\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eset-key-partition-list\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-S\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eapple-tool:,apple:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\\\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003e-k\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;$KEYCHAIN_PASSWORD\u0026quot;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n\n    \u003cspan class=\"hljs-string\"\u003esecurity\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003elist-keychain\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-d\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003euser\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e-s\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e$KEYCHAIN_PATH\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThat\u0026#39;s a throwaway keychain with a random password, thrown away along with the\nrunner. The \u003ccode\u003eset-key-partition-list\u003c/code\u003e call is the non-obvious one — leave it out\nand \u003ccode\u003ecodesign\u003c/code\u003e hangs forever, waiting for a UI prompt that nobody is ever going\nto answer.\u003c/p\u003e\n\u003cp\u003eThen pass the credentials through to the build:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-yaml\"\u003e\u003cspan class=\"hljs-bullet\"\u003e-\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ename:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eBuild\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eartifacts\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003erun:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eyarn\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003emake\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eenv:\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_APP_SPECIFIC_PASSWORD:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_APP_SPECIFIC_PASSWORD\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_ID:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_ID\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_TEAM_ID:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_TEAM_ID\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIf you support Intel Macs, you\u0026#39;ll need a second runner. \u003ccode\u003emacos-latest\u003c/code\u003e is Apple\nsilicon, so that\u0026#39;s the only architecture it can build correctly. Reach for\n\u003ccode\u003e--arch=x64\u003c/code\u003e and you\u0026#39;ll get a broken app the moment you have native\ndependencies, because those ship per-architecture prebuilt bindings and your\npackage manager only installs the one matching the runner.\u003c/p\u003e\n\u003cp\u003eUse a separate job instead:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-yaml\"\u003e\u003cspan class=\"hljs-attr\"\u003estrategy:\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003ematrix:\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eos:\u003c/span\u003e [\u003cspan class=\"hljs-string\"\u003emacos-latest\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003emacos-15-intel\u003c/span\u003e]\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ccode\u003emacos-15-intel\u003c/code\u003e is GitHub\u0026#39;s Intel image, and it\u0026#39;s worth knowing that it\u0026#39;s the\nlast one. It\u0026#39;s available until August 2027, and after that x86_64 isn\u0026#39;t\nsupported on GitHub Actions at all.\u003c/p\u003e\n\u003cp\u003eThere are also two guards worth adding, because that environment-variable gate\nhas a nasty edge to it. If a secret goes missing in CI, \u003ccode\u003eosxSign\u003c/code\u003e never runs and\nyou happily publish an unsigned app. That\u0026#39;s the exact bug you set out to fix,\nexcept now the release looks like a success.\u003c/p\u003e\n\u003cp\u003eSo check for them explicitly:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-yaml\"\u003e\u003cspan class=\"hljs-bullet\"\u003e-\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ename:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eCheck\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eApple\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esigning\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eif:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003estartsWith(matrix.os,\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026#x27;macos\u0026#x27;\u003c/span\u003e\u003cspan class=\"hljs-string\"\u003e)\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eshell:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ebash\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003eenv:\u003c/span\u003e\n    \u003cspan class=\"hljs-attr\"\u003eAPPLE_TEAM_ID:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e${{\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003esecrets.APPLE_TEAM_ID\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e}}\u003c/span\u003e\n    \u003cspan class=\"hljs-comment\"\u003e# ...and the rest\u003c/span\u003e\n  \u003cspan class=\"hljs-attr\"\u003erun:\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e|\n    missing=()\n\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003efor\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ename\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ein\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eAPPLE_APP_SPECIFIC_PASSWORD\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eAPPLE_CERTIFICATE\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\\\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003eAPPLE_CERTIFICATE_PASSWORD\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eAPPLE_ID\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eAPPLE_TEAM_ID;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003edo\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003eif\u003c/span\u003e [ \u003cspan class=\"hljs-string\"\u003e-z\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;${!name}\u0026quot;\u003c/span\u003e ]\u003cspan class=\"hljs-string\"\u003e;\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003ethen\u003c/span\u003e\n        \u003cspan class=\"hljs-string\"\u003emissing+=(\u0026quot;$name\u0026quot;)\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003efi\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003edone\u003c/span\u003e\n\n    \u003cspan class=\"hljs-string\"\u003eif\u003c/span\u003e [ \u003cspan class=\"hljs-string\"\u003e$\u003c/span\u003e{\u003cspan class=\"hljs-comment\"\u003e#missing[@]} -gt 0 ]; then\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;::error::Missing repository secrets: ${missing[*]}. Without them the app is unsigned and macOS reports it as damaged.\u0026quot;\u003c/span\u003e\n      \u003cspan class=\"hljs-string\"\u003eexit\u003c/span\u003e \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e\n    \u003cspan class=\"hljs-string\"\u003efi\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eWhile you\u0026#39;re in there, check that the makers actually produced something. A bare\n\u003ccode\u003efind -exec\u003c/code\u003e exits 0 when nothing matches, so a maker that failed leaves you\nwith a green checkmark and a release that has no installer for that platform:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003e\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e [ \u003cspan class=\"hljs-variable\"\u003e${#artifacts[@]}\u003c/span\u003e -eq 0 ]; \u003cspan class=\"hljs-keyword\"\u003ethen\u003c/span\u003e\n  \u003cspan class=\"hljs-built_in\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e\u0026quot;
340::error::No installers found in out/make. Check the build step.\u0026quot;\u003c/span\u003e\n  \u003cspan class=\"hljs-built_in\"\u003eexit\u003c/span\u003e 1\n\u003cspan class=\"hljs-keyword\"\u003efi\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eBoth of these guards exist for the same reason. The default behaviour is to fail\nsilently, and in a release pipeline that\u0026#39;s the worst kind of failure there is.\u003c/p\u003e\n\u003cp\u003eThat leaves verification, which is three commands. Run them on the built app and\nactually read the output:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003ecodesign --verify --deep --strict --verbose=2 out/MyApp-darwin-arm64/MyApp.app\nspctl --assess --\u003cspan class=\"hljs-built_in\"\u003etype\u003c/span\u003e execute --verbose out/MyApp-darwin-arm64/MyApp.app\nxcrun stapler validate out/MyApp-darwin-arm64/MyApp.app\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eHere\u0026#39;s what you want to see:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-text\"\u003eMyApp.app: valid on disk\nMyApp.app: satisfies its Designated Requirement\nMyApp.app: accepted\nsource=Notarized Developer ID\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ccode\u003ecodesign -dv\u003c/code\u003e is worth a look too. Check three things: that the identifier is\nyour bundle ID and not \u003ccode\u003ecom.github.Electron\u003c/code\u003e, that \u003ccode\u003eTeamIdentifier\u003c/code\u003e has a value,\nand that the flags read \u003ccode\u003eflags=0x10000(runtime)\u003c/code\u003e. That last one is your proof\nthat the hardened runtime is actually on:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs language-bash\"\u003ecodesign -dv out/MyApp-darwin-arm64/MyApp.app\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThen launch the signed build and click around a bit. This matters more than it\nsounds, because the hardened runtime is exactly where native modules break, and\na signed app is the first time that code path ever runs. So if you ship a native\nbinding, open a connection, read a file, do the thing.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eHave you shipped an Electron app to macOS? Let me know in the comments if you\nran into any traps I missed!\u003c/em\u003e\u003c/p\u003e\n"])</script>
340<script>self.__next_f.push([1,"8:[[\"$\",\"div\",null,{\"className\":\"\\n        w-full\\n        box-border\\n        px-8 py-2 md:py-3\\n        fixed top-0\\n        z-20\\n        text-white\\n      \",\"id\":\"site-header\",\"style\":{\"backdropFilter\":\"blur(24px)\",\"backgroundColor\":\"rgba(113, 34,47, 0.95)\"},\"children\":[[\"$\",\"$L12\",null,{\"className\":\"absolute inset-0 h-full w-full\",\"count\":3,\"mode\":\"embers\",\"scale\":0.6}],[\"$\",\"div\",null,{\"className\":\"\\n          relative z-10\\n          w-full\\n          flex items-center\\n          max-w-4xl\\n          mx-auto\\n        \",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex-1\",\"children\":[\"$\",\"$L13\",null,{\"className\":\"text-sm font-semibold\",\"href\":\"/\",\"style\":{\"fontFamily\":\"var(--font-poppins)\"},\"children\":\"Christoffer Artmann\"}]}],[\"$\",\"nav\",null,{\"className\":\"\\n            flex gap-4\\n            font-medium\\n            text-xs\\n          \",\"children\":[[\"$\",\"div\",null,{\"children\":[\"$\",\"$L13\",null,{\"className\":\"hover:underline\",\"href\":\"/\",\"children\":\"Posts\"}]}],[\"$\",\"div\",null,{\"children\":[\"$\",\"$L13\",null,{\"className\":\"hover:underline\",\"href\":\"/projects\",\"children\":\"Projects\"}]}]]}]]}]]}],[\"$\",\"$L14\",null,{}],[\"$\",\"$L15\",null,{}],[[\"$\",\"div\",null,{\"className\":\"container mx-auto p-4 pb-8 md:py-8 max-w-4xl\",\"children\":[[\"$\",\"article\",null,{\"className\":\"w-full text-gray-800 leading-loose pt-16 md:pt-24 space-y-8\",\"children\":[[\"$\",\"header\",null,{\"className\":\"space-y-3\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-2xl md:text-3xl font-semibold\",\"children\":\"Signing, Notarizing, and Publishing an Electron App for macOS\"}],[\"$\",\"p\",null,{\"className\":\"text-lg md:text-xl\",\"children\":\"I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here's everything I had to figure out to fix it.\"}],[\"$\",\"p\",null,{\"className\":\"mb-8 text-sm text-gray-600\",\"children\":\"August 03, 2026\"}]]}],[\"$\",\"img\",null,{\"alt\":\"Signing, Notarizing, and Publishing an Electron App for macOS\",\"className\":\"w-full h-auto border-gray-300 shadow-lg overflow-x-hidden break-words\",\"src\":\"/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp\"}],[\"$\",\"div\",null,{\"className\":\"article-content text-base leading-relaxed text-gray-900 pb-8 md:pb-16\",\"dangerouslySetInnerHTML\":{\"__html\":\"$16\"}}],\"$L17\"]}],\"$L18\"]}],\"$L19\"]]\n"])</script>
340<script>self.__next_f.push([1,"a:null\n"])</script>
340<script>self.__next_f.push([1,"f:[[\"$\",\"title\",\"0\",{\"children\":\"Signing, Notarizing, and Publishing an Electron App for macOS\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here's everything I had to figure out to fix it.\"}],[\"$\",\"meta\",\"2\",{\"property\":\"og:title\",\"content\":\"Signing, Notarizing, and Publishing an Electron App for macOS\"}],[\"$\",\"meta\",\"3\",{\"property\":\"og:description\",\"content\":\"I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here's everything I had to figure out to fix it.\"}],[\"$\",\"meta\",\"4\",{\"property\":\"og:url\",\"content\":\"https://www.artmann.co/articles/signing-notarizing-and-publishing-an-electron-app-for-mac-os\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:image\",\"content\":\"https://www.artmann.co/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"7\",{\"name\":\"twitter:card\",\"content\":\"summary\"}],[\"$\",\"meta\",\"8\",{\"name\":\"twitter:title\",\"content\":\"Signing, Notarizing, and Publishing an Electron App for macOS\"}],[\"$\",\"meta\",\"9\",{\"name\":\"twitter:description\",\"content\":\"I shipped a macOS build that nobody could open. macOS said the app was damaged, which is a lie — it was a code signing problem all along. Here's everything I had to figure out to fix it.\"}],[\"$\",\"meta\",\"10\",{\"name\":\"twitter:image\",\"content\":\"https://www.artmann.co/images/covers/signing-notarizing-and-publishing-an-electron-app-for-mac-os.webp\"}],[\"$\",\"link\",\"11\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"12\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"type\":\"image/png\",\"sizes\":\"32x32\"}],[\"$\",\"link\",\"13\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"type\":\"image/png\",\"sizes\":\"16x16\"}],[\"$\",\"link\",\"14\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$L1a\",\"15\",{}]]\n"])</script>
340<script>self.__next_f.push([1,"1b:I[33287,[\"/_next/static/chunks/1539c1wk17cta.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0x7k4xycyd2~c.js\"],\"ArticleClientEffects\"]\n"])</script>
340<script>self.__next_f.push([1,"17:[\"$\",\"div\",null,{\"className\":\"relative flex flex-col items-center gap-3 pb-6 pt-4 text-center\",\"children\":[[\"$\",\"$L12\",null,{\"className\":\"absolute inset-0 h-full w-full\",\"count\":3,\"mode\":\"fireflies\"}],[\"$\",\"svg\",null,{\"aria-hidden\":true,\"className\":\"\",\"height\":44,\"viewBox\":\"0 0 64 56\",\"width\":50.285714285714285,\"children\":[[\"$\",\"ellipse\",null,{\"className\":\"campfire-glow\",\"cx\":\"32\",\"cy\":\"44\",\"fill\":\"#f97316\",\"rx\":\"22\",\"ry\":\"10\"}],[\"$\",\"circle\",null,{\"className\":\"campfire-spark\",\"cx\":\"26\",\"cy\":\"24\",\"fill\":\"#fbbf24\",\"r\":\"1\"}],[\"$\",\"circle\",null,{\"className\":\"campfire-spark\",\"cx\":\"39\",\"cy\":\"28\",\"fill\":\"#fcd34d\",\"r\":\"0.8\",\"style\":{\"animationDelay\":\"-1.4s\"}}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-outer\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 12 C38 22 43 30 43 38 C43 45 38 49 32 49 C26 49 21 45 21 38 C21 30 26 22 32 12 Z\",\"fill\":\"#f59e0b\"}]}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-mid\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 20 C36 27 39.5 32 39.5 38 C39.5 43.5 36 46.5 32 46.5 C28 46.5 24.5 43.5 24.5 38 C24.5 32 28 27 32 20 Z\",\"fill\":\"#f97316\"}]}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-inner\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 29 C34.5 33.5 36 36.5 36 40 C36 43.5 34 45 32 45 C30 45 28 43.5 28 40 C28 36.5 29.5 33.5 32 29 Z\",\"fill\":\"#fde68a\"}]}],[\"$\",\"rect\",null,{\"fill\":\"#4a2f22\",\"height\":\"5\",\"rx\":\"2.5\",\"transform\":\"rotate(14 32 48.5)\",\"width\":\"26\",\"x\":\"19\",\"y\":\"46\"}],[\"$\",\"rect\",null,{\"fill\":\"#3a241a\",\"height\":\"5\",\"rx\":\"2.5\",\"transform\":\"rotate(-14 32 48.5)\",\"width\":\"26\",\"x\":\"19\",\"y\":\"46\"}]]}],[\"$\",\"p\",null,{\"className\":\"m-0 text-sm text-gray-500\",\"children\":\"You've reached camp. Thanks for reading.\"}]]}]\n"])</script>
340<script>self.__next_f.push([1,"18:[\"$\",\"$L1b\",null,{\"slug\":\"signing-notarizing-and-publishing-an-electron-app-for-mac-os\",\"title\":\"Signing, Notarizing, and Publishing an Electron App for macOS\"}]\n1c:T288a,"])</script>
340<script>self.__next_f.push([1,"M-10,90 L-10,79 L-15.6,79 L-7.4,63.7 L-10.5,65.4 L-8.8,64.5 L-2.3,52.8 L-5.4,54.5 L-3.7,53.6 L1.5,42.7 L6.6,53.6 L8.3,54.5 L5.2,52.8 L11.7,64.5 L13.4,65.4 L10.3,63.7 L18.6,79 L8.6,79 L16.7,65.1 L13.7,66.6 L15.4,65.8 L21.8,55.2 L18.7,56.7 L20.4,55.9 L25.5,45.9 L30.6,55.9 L32.3,56.7 L29.2,55.2 L35.7,65.8 L37.3,66.6 L34.3,65.1 L42.4,79 L30.2,79 L39.4,69.6 L36,70.6 L37.9,70.1 L45.1,62.9 L41.7,63.9 L43.6,63.3 L49.3,56.6 L55,63.3 L57,63.9 L53.5,62.9 L60.8,70.1 L62.7,70.6 L59.2,69.6 L68.4,79 L49.8,79 L60.1,69.5 L56.3,70.5 L58.4,69.9 L66.6,62.7 L62.7,63.7 L64.9,63.1 L71.4,56.4 L77.8,63.1 L80,63.7 L76.1,62.7 L84.3,69.9 L86.5,70.5 L82.6,69.5 L92.9,79 L76.4,79 L85.6,70.5 L82.1,71.4 L84,70.9 L91.3,64.5 L87.9,65.4 L89.8,64.9 L95.5,58.8 L101.3,64.9 L103.2,65.4 L99.7,64.5 L107,70.9 L108.9,71.4 L105.5,70.5 L114.7,79 L96.7,79 L105.1,71.2 L101.9,72 L103.7,71.6 L110.3,65.6 L107.2,66.5 L108.9,66 L114.1,60.4 L119.3,66 L121.1,66.5 L118,65.6 L124.6,71.6 L126.3,72 L123.2,71.2 L131.5,79 L115.9,79 L123.9,71.9 L120.9,72.6 L122.6,72.2 L129,66.8 L126,67.5 L127.6,67.1 L132.7,62 L137.7,67.1 L139.4,67.5 L136.4,66.8 L142.7,72.2 L144.4,72.6 L141.4,71.9 L149.5,79 L131.1,79 L137.7,70.7 L135.2,71.6 L136.6,71.1 L141.8,64.7 L139.4,65.6 L140.7,65.1 L144.9,59.2 L149,65.1 L150.4,65.6 L147.9,64.7 L153.2,71.1 L154.5,71.6 L152.1,70.7 L158.7,79 L149.4,79 L157.5,71.7 L154.5,72.4 L156.2,72 L162.6,66.4 L159.6,67.2 L161.3,66.8 L166.4,61.5 L171.5,66.8 L173.2,67.2 L170.1,66.4 L176.5,72 L178.2,72.4 L175.2,71.7 L183.3,79 L168.1,79 L176.1,71.4 L173.1,72.2 L174.7,71.7 L181,65.9 L178,66.7 L179.7,66.3 L184.7,60.8 L189.6,66.3 L191.3,66.7 L188.3,65.9 L194.6,71.7 L196.3,72.2 L193.3,71.4 L201.3,79 L184.5,79 L193.7,72.3 L190.3,73 L192.2,72.6 L199.5,67.6 L196,68.3 L197.9,67.9 L203.7,63.1 L209.4,67.9 L211.3,68.3 L207.9,67.6 L215.2,72.6 L217.1,73 L213.6,72.3 L222.8,79 L203.5,79 L212.7,70.8 L209.2,71.7 L211.1,71.2 L218.4,65 L215,65.9 L216.9,65.4 L222.6,59.6 L228.3,65.4 L230.3,65.9 L226.8,65 L234.1,71.2 L236,71.7 L232.6,70.8 L241.7,79 L225.5,79 L231.3,71.9 L229.1,72.6 L230.3,72.2 L234.9,66.8 L232.7,67.5 L233.9,67.1 L237.5,62 L241.1,67.1 L242.3,67.5 L240.2,66.8 L244.7,72.2 L245.9,72.6 L243.8,71.9 L249.5,79 L237,79 L243.3,70.9 L240.9,71.8 L242.3,71.3 L247.3,65.1 L244.9,66 L246.2,65.5 L250.2,59.7 L254.2,65.5 L255.5,66 L253.1,65.1 L258.2,71.3 L259.5,71.8 L257.1,70.9 L263.5,79 L256.7,79 L264.4,69.9 L261.5,70.8 L263.1,70.3 L269.1,63.3 L266.3,64.3 L267.9,63.8 L272.6,57.2 L277.4,63.8 L279,64.3 L276.1,63.3 L282.2,70.3 L283.8,70.8 L280.9,69.9 L288.5,79 L274.7,79 L283.2,70.8 L280,71.7 L281.7,71.2 L288.4,64.9 L285.3,65.8 L287,65.3 L292.3,59.5 L297.6,65.3 L299.4,65.8 L296.2,64.9 L302.9,71.2 L304.7,71.7 L301.5,70.8 L310,79 L296.4,79 L306.8,68.5 L302.9,69.6 L305.1,69 L313.3,60.9 L309.4,62.1 L311.6,61.4 L318.1,53.9 L324.6,61.4 L326.7,62.1 L322.8,60.9 L331.1,69 L333.2,69.6 L329.3,68.5 L339.7,79 L324.4,79 L333,68.5 L329.8,69.6 L331.6,69 L338.5,60.9 L335.2,62.1 L337,61.4 L342.4,53.9 L347.9,61.4 L349.7,62.1 L346.4,60.9 L353.3,69 L355.1,69.6 L351.8,68.5 L360.5,79 L342.4,79 L351.2,64.8 L347.9,66.3 L349.7,65.4 L356.6,54.6 L353.4,56.1 L355.2,55.3 L360.7,45.1 L366.2,55.3 L368,56.1 L364.7,54.6 L371.6,65.4 L373.5,66.3 L370.2,64.8 L379,79 L364.6,79 L372.1,63.4 L369.3,65.1 L370.8,64.2 L376.8,52.3 L374,54 L375.5,53 L380.2,41.9 L384.8,53 L386.4,54 L383.6,52.3 L389.5,64.2 L391.1,65.1 L388.3,63.4 L395.7,79 L377.8,79 L386.5,65.5 L383.2,66.9 L385,66.1 L391.9,55.8 L388.7,57.3 L390.5,56.5 L395.9,46.8 L401.4,56.5 L403.2,57.3 L399.9,55.8 L406.8,66.1 L408.6,66.9 L405.4,65.5 L414.1,79 L406.1,79 L414.8,62.4 L411.5,64.2 L413.3,63.2 L420.2,50.5 L416.9,52.3 L418.7,51.3 L424.2,39.4 L429.6,51.3 L431.4,52.3 L428.1,50.5 L435,63.2 L436.8,64.2 L433.6,62.4 L442.3,79 L425.5,79 L432.6,59.6 L429.9,61.7 L431.4,60.5 L437,45.8 L434.3,47.8 L435.8,46.7 L440.2,32.8 L444.6,46.7 L446.1,47.8 L443.5,45.8 L449.1,60.5 L450.5,61.7 L447.9,59.6 L455,79 L436.5,79 L445.2,58.8 L442,61 L443.8,59.8 L450.7,44.4 L447.4,46.6 L449.2,45.4 L454.6,31 L460.1,45.4 L461.9,46.6 L458.6,44.4 L465.5,59.8 L467.3,61 L464.1,58.8 L472.7,79 L459.8,79 L468.5,62.5 L465.2,64.3 L467.1,63.3 L474,50.8 L470.7,52.5 L472.5,51.6 L478,39.8 L483.5,51.6 L485.3,52.5 L482,50.8 L489,63.3 L490.8,64.3 L487.5,62.5 L496.3,79 L476.3,79 L486.2,62 L482.5,63.8 L484.5,62.8 L492.3,49.8 L488.6,51.6 L490.7,50.6 L496.8,38.5 L503,50.6 L505.1,51.
3406 L501.4,49.8 L509.2,62.8 L511.2,63.8 L507.5,62 L517.4,79 L500.6,79 L508.7,55.4 L505.7,57.9 L507.4,56.5 L513.8,38.6 L510.7,41.1 L512.4,39.7 L517.5,22.8 L522.6,39.7 L524.3,41.1 L521.3,38.6 L527.7,56.5 L529.4,57.9 L526.4,55.4 L534.5,79 L520.4,79 L529.7,58.9 L526.2,61 L528.1,59.8 L535.5,44.5 L532,46.7 L533.9,45.5 L539.7,31.1 L545.5,45.5 L547.4,46.7 L544,44.5 L551.3,59.8 L553.2,61 L549.7,58.9 L559,79 L544.2,79 L554.6,60.4 L550.7,62.4 L552.8,61.3 L561,47.1 L557.1,49.1 L559.3,48 L565.8,34.8 L572.3,48 L574.4,49.1 L570.5,47.1 L578.7,61.3 L580.9,62.4 L577,60.4 L587.4,79 L568.9,79 L577.2,61.8 L574.1,63.6 L575.9,62.6 L582.5,49.5 L579.3,51.3 L581.1,50.3 L586.3,38 L591.5,50.3 L593.2,51.3 L590.1,49.5 L596.7,62.6 L598.4,63.6 L595.3,61.8 L603.6,79 L596,79 L604,60.5 L601,62.5 L602.7,61.4 L609.1,47.3 L606,49.3 L607.7,48.2 L612.8,35 L617.8,48.2 L619.5,49.3 L616.5,47.3 L622.9,61.4 L624.5,62.5 L621.5,60.5 L629.6,79 L616.2,79 L622.6,60.8 L620.2,62.8 L621.5,61.7 L626.6,47.9 L624.2,49.8 L625.6,48.7 L629.6,35.8 L633.6,48.7 L634.9,49.8 L632.5,47.9 L637.6,61.7 L638.9,62.8 L636.5,60.8 L642.9,79 L635,79 L642.3,54.4 L639.6,57 L641.1,55.5 L646.9,36.8 L644.2,39.4 L645.7,37.9 L650.3,20.3 L654.9,37.9 L656.5,39.4 L653.7,36.8 L659.5,55.5 L661.1,57 L658.3,54.4 L665.7,79 L653.1,79 L663.1,57.7 L659.3,59.9 L661.4,58.7 L669.3,42.4 L665.6,44.7 L667.7,43.4 L673.9,28.2 L680.1,43.4 L682.2,44.7 L678.5,42.4 L686.4,58.7 L688.4,59.9 L684.7,57.7 L694.7,79 L676.6,79 L686.4,62.9 L682.7,64.7 L684.8,63.7 L692.5,51.5 L688.8,53.2 L690.9,52.2 L697,40.8 L703.2,52.2 L705.2,53.2 L701.5,51.5 L709.3,63.7 L711.3,64.7 L707.7,62.9 L717.5,79 L710.9,79 L717.4,57.5 L714.9,59.8 L716.3,58.5 L721.4,42.1 L719,44.4 L720.3,43.1 L724.4,27.7 L728.4,43.1 L729.8,44.4 L727.4,42.1 L732.5,58.5 L733.8,59.8 L731.4,57.5 L737.9,79 L727.2,79 L734.2,60.5 L731.6,62.5 L733,61.4 L738.6,47.4 L735.9,49.3 L737.4,48.2 L741.8,35 L746.1,48.2 L747.6,49.3 L745,47.4 L750.5,61.4 L752,62.5 L749.4,60.5 L756.4,79 L744.7,79 L752.5,66 L749.6,67.4 L751.2,66.6 L757.4,56.7 L754.4,58.1 L756.1,57.3 L761,48.1 L765.8,57.3 L767.5,58.1 L764.5,56.7 L770.7,66.6 L772.4,67.4 L769.4,66 L777.3,79 L761.1,79 L767.3,62.7 L764.9,64.4 L766.2,63.4 L771.2,51 L768.8,52.8 L770.1,51.8 L774,40.1 L777.9,51.8 L779.2,52.8 L776.9,51 L781.8,63.4 L783.1,64.4 L780.7,62.7 L787,79 L774.5,79 L784.3,64.2 L780.6,65.8 L782.7,64.9 L790.5,53.7 L786.8,55.2 L788.9,54.4 L795,43.8 L801.2,54.4 L803.2,55.2 L799.5,53.7 L807.3,64.9 L809.4,65.8 L805.7,64.2 L815.6,79 L800.6,79 L809.3,64.7 L806,66.3 L807.9,65.4 L814.8,54.5 L811.5,56.1 L813.3,55.2 L818.8,45 L824.3,55.2 L826.1,56.1 L822.8,54.5 L829.8,65.4 L831.6,66.3 L828.3,64.7 L837.1,79 L821.9,79 L830.9,69 L827.5,70.1 L829.4,69.5 L836.4,61.9 L833.1,63 L834.9,62.4 L840.5,55.3 L846.1,62.4 L847.9,63 L844.6,61.9 L851.6,69.5 L853.5,70.1 L850.2,69 L859.1,79 L842.5,79 L848.7,67.7 L846.4,68.9 L847.7,68.2 L852.6,59.6 L850.3,60.8 L851.6,60.2 L855.5,52.1 L859.4,60.2 L860.7,60.8 L858.3,59.6 L863.2,68.2 L864.5,68.9 L862.2,67.7 L868.4,79 L859.8,79 L866.7,69.3 L864.1,70.3 L865.6,69.8 L871.1,62.4 L868.5,63.4 L869.9,62.8 L874.3,55.9 L878.6,62.8 L880.1,63.4 L877.5,62.4 L883,69.8 L884.4,70.3 L881.8,69.3 L888.8,79 L874.9,79 L883.8,70.1 L880.5,71.1 L882.3,70.5 L889.4,63.8 L886,64.7 L887.9,64.2 L893.5,57.9 L899,64.2 L900.9,64.7 L897.6,63.8 L904.6,70.5 L906.5,71.1 L903.1,70.1 L912.1,79 L893.5,79 L902.7,69.3 L899.2,70.3 L901.1,69.7 L908.4,62.3 L905,63.4 L906.9,62.8 L912.6,55.9 L918.3,62.8 L920.3,63.4 L916.8,62.3 L924.1,69.7 L926,70.3 L922.6,69.3 L931.7,79 L922.3,79 L931.6,70.8 L928.1,71.7 L930,71.2 L937.4,65 L933.9,65.9 L935.9,65.4 L941.7,59.5 L947.5,65.4 L949.5,65.9 L946,65 L953.3,71.2 L955.3,71.7 L951.8,70.8 L961.1,79 L943.5,79 L952.5,71 L949.1,71.8 L951,71.4 L958.1,65.2 L954.7,66.1 L956.6,65.6 L962.2,59.9 L967.8,65.6 L969.7,66.1 L966.3,65.2 L973.4,71.4 L975.3,71.8 L971.9,71 L980.9,79 L968.6,79 L975.8,71.9 L973.1,72.7 L974.6,72.2 L980.2,66.8 L977.6,67.6 L979,67.2 L983.5,62.1 L988,67.2 L989.5,67.6 L986.8,66.8 L992.4,72.2 L993.9,72.7 L991.2,71.9 L998.4,79 L989.8,79 L997.2,71.4 L994.4,72.2 L996,71.8 L1001.9,66 L999.1,66.8 L1000.6,66.3 L1005.3,60.9 L1009.9,66.3 L1011.4,66.8 L1008.7,66 L1014.5,71.8 L1016.1,72.2 L1013.3,71.4 L1020.7,79 L1009.4,79 L1017.4,70.8 L1014.4,71.7 L1016.1,71.2 L1022.5,65 L1019.4,65.9 L1021.1,65.4 L1026.2,59.6 L1031.2,65.4 L1032.9,65.9 L1029.9,65 L1036.2,71.2 L1037.9,71.7 L1034.9,70.8 L1043,79 L1036.7,79 L1043.4,71.5 L1040.8,72.3 L1042.2,71.9 L1047.5,66.1 L1045,67 L1046.4,66.5 L1050.6,61.2 L10
34054.8,66.5 L1056.2,67 L1053.7,66.1 L1059,71.9 L1060.4,72.3 L1057.9,71.5 L1064.6,79 L1057,79 L1065.9,71.8 L1062.6,72.5 L1064.4,72.1 L1071.4,66.6 L1068.1,67.4 L1070,66.9 L1075.5,61.8 L1081,66.9 L1082.9,67.4 L1079.6,66.6 L1086.6,72.1 L1088.4,72.5 L1085.1,71.8 L1093.9,79 L1076.4,79 L1083.2,71.4 L1080.7,72.2 L1082.1,71.8 L1087.5,66 L1084.9,66.8 L1086.4,66.3 L1090.6,60.9 L1094.9,66.3 L1096.3,66.8 L1093.8,66 L1099.2,71.8 L1100.6,72.2 L1098,71.4 L1104.8,79 L1089,79 L1096.6,68.6 L1093.7,69.7 L1095.3,69.1 L1101.3,61.2 L1098.5,62.3 L1100,61.7 L1104.8,54.2 L1109.5,61.7 L1111.1,62.3 L1108.3,61.2 L1114.3,69.1 L1115.8,69.7 L1113,68.6 L1120.6,79 L1109.3,79 L1117.8,68.9 L1114.6,70 L1116.4,69.4 L1123.2,61.7 L1120,62.8 L1121.7,62.2 L1127.1,55 L1132.4,62.2 L1134.2,62.8 L1131,61.7 L1137.7,69.4 L1139.5,70 L1136.3,68.9 L1144.8,79 L1132.4,79 L1142.5,69 L1138.7,70.1 L1140.9,69.5 L1148.9,61.9 L1145.1,62.9 L1147.2,62.3 L1153.5,55.2 L1159.9,62.3 L1162,62.9 L1158.2,61.9 L1166.2,69.5 L1168.3,70.1 L1164.5,69 L1174.6,79 L1156.4,79 L1166.5,69 L1162.7,70.1 L1164.8,69.5 L1172.9,61.9 L1169.1,63 L1171.2,62.4 L1177.6,55.3 L1183.9,62.4 L1186,63 L1182.2,61.9 L1190.3,69.5 L1192.4,70.1 L1188.6,69 L1198.8,79 L1183.5,79 L1189.9,65.7 L1187.5,67.1 L1188.8,66.3 L1193.9,56.2 L1191.5,57.6 L1192.9,56.8 L1196.9,47.3 L1200.9,56.8 L1202.3,57.6 L1199.9,56.2 L1205,66.3 L1206.3,67.1 L1203.9,65.7 L1210.3,79 L1196.2,79 L1206.4,65.3 L1202.6,66.8 L1204.7,66 L1212.7,55.6 L1208.9,57.1 L1211,56.2 L1217.3,46.5 L1223.6,56.2 L1225.8,57.1 L1222,55.6 L1230,66 L1232.1,66.8 L1228.3,65.3 L1238.4,79 L1210,79 L1210,90 Z"])</script>
340<script>self.__next_f.push([1,"19:[\"$\",\"footer\",null,{\"className\":\"mt-8\",\"children\":[[\"$\",\"div\",null,{\"className\":\"-mb-px\",\"children\":[\"$\",\"svg\",null,{\"aria-hidden\":true,\"className\":\"block h-8 w-full text-burgundy sm:h-12 md:h-16\",\"preserveAspectRatio\":\"none\",\"viewBox\":\"0 0 1200 80\",\"children\":[[\"$\",\"path\",null,{\"d\":\"$1c\",\"fill\":\"currentColor\",\"fillOpacity\":\"0.45\"}],\"$L1d\"]}]}],\"$L1e\"]}]\n"])</script>
340<script>self.__next_f.push([1,":HL[\"/images/christoffer-artmann.jpg\",\"image\"]\n1f:T3487,"])</script>
340<script>self.__next_f.push([1,"M-10,90 L-10,78 L-14.1,78 L-7.7,70.4 L-10.1,71.2 L-8.8,70.8 L-3.7,65 L-6.1,65.8 L-4.8,65.3 L-0.8,59.9 L3.2,65.3 L4.5,65.8 L2.2,65 L7.2,70.8 L8.5,71.2 L6.1,70.4 L12.5,78 L0.6,78 L7,69.2 L4.6,70.2 L5.9,69.6 L11,63 L8.6,63.9 L10,63.4 L14,57.1 L18,63.4 L19.3,63.9 L16.9,63 L22,69.6 L23.3,70.2 L20.9,69.2 L27.3,78 L17.5,78 L23.5,69.9 L21.3,70.8 L22.5,70.3 L27.3,64.2 L25,65 L26.3,64.5 L30,58.8 L33.8,64.5 L35,65 L32.8,64.2 L37.5,70.3 L38.8,70.8 L36.5,69.9 L42.5,78 L35.2,78 L42.2,70.3 L39.6,71.1 L41.1,70.7 L46.7,64.8 L44,65.7 L45.5,65.2 L49.9,59.7 L54.3,65.2 L55.8,65.7 L53.1,64.8 L58.7,70.7 L60.2,71.1 L57.5,70.3 L64.6,78 L52,78 L57.1,70.9 L55.2,71.7 L56.3,71.3 L60.4,65.9 L58.4,66.6 L59.5,66.2 L62.7,61.2 L66,66.2 L67,66.6 L65.1,65.9 L69.2,71.3 L70.3,71.7 L68.3,70.9 L73.5,78 L65.5,78 L70,68.9 L68.3,69.9 L69.2,69.4 L72.8,62.5 L71.1,63.4 L72,62.9 L74.8,56.4 L77.6,62.9 L78.5,63.4 L76.9,62.5 L80.4,69.4 L81.3,69.9 L79.6,68.9 L84.1,78 L75.7,78 L83.6,69.3 L80.6,70.2 L82.3,69.7 L88.5,63 L85.6,63.9 L87.2,63.4 L92.2,57.2 L97.1,63.4 L98.7,63.9 L95.8,63 L102,69.7 L103.7,70.2 L100.7,69.3 L108.6,78 L98,78 L104.8,68.9 L102.2,69.8 L103.7,69.3 L109.1,62.3 L106.5,63.3 L107.9,62.8 L112.2,56.2 L116.5,62.8 L117.9,63.3 L115.3,62.3 L120.7,69.3 L122.2,69.8 L119.6,68.9 L126.4,78 L108.7,78 L117.3,65.8 L114.1,67.1 L115.8,66.4 L122.6,57.1 L119.4,58.4 L121.2,57.7 L126.5,49 L131.8,57.7 L133.6,58.4 L130.4,57.1 L137.2,66.4 L138.9,67.1 L135.7,65.8 L144.3,78 L130.4,78 L135.9,64.7 L133.9,66.2 L135,65.4 L139.4,55.3 L137.3,56.7 L138.5,55.9 L141.9,46.4 L145.4,55.9 L146.5,56.7 L144.4,55.3 L148.8,65.4 L149.9,66.2 L147.9,64.7 L153.4,78 L147.3,78 L151.8,63 L150.1,64.6 L151.1,63.7 L154.7,52.3 L153,53.9 L153.9,53 L156.7,42.3 L159.6,53 L160.5,53.9 L158.8,52.3 L162.4,63.7 L163.4,64.6 L161.7,63 L166.2,78 L159.7,78 L163.7,65.7 L162.2,67 L163,66.2 L166.2,56.8 L164.7,58.2 L165.5,57.4 L168,48.6 L170.5,57.4 L171.3,58.2 L169.8,56.8 L172.9,66.2 L173.8,67 L172.3,65.7 L176.2,78 L167.7,78 L174,64.1 L171.6,65.6 L173,64.8 L178,54.2 L175.6,55.7 L176.9,54.9 L180.9,45 L184.9,54.9 L186.2,55.7 L183.8,54.2 L188.9,64.8 L190.2,65.6 L187.8,64.1 L194.2,78 L186.6,78 L190.9,61 L189.3,62.8 L190.2,61.8 L193.6,48.8 L192,50.7 L192.8,49.6 L195.5,37.5 L198.2,49.6 L199.1,50.7 L197.5,48.8 L200.8,61.8 L201.7,62.8 L200.1,61 L204.4,78 L195.3,78 L202.2,63.2 L199.6,64.8 L201.1,63.9 L206.5,52.6 L203.9,54.2 L205.4,53.3 L209.7,42.7 L214,53.3 L215.4,54.2 L212.8,52.6 L218.3,63.9 L219.7,64.8 L217.1,63.2 L224,78 L211.7,78 L217.2,61.8 L215.1,63.5 L216.3,62.5 L220.7,50.2 L218.6,51.9 L219.7,50.9 L223.2,39.3 L226.7,50.9 L227.8,51.9 L225.7,50.2 L230.1,62.5 L231.3,63.5 L229.2,61.8 L234.7,78 L224,78 L231.5,61.5 L228.7,63.3 L230.2,62.3 L236.2,49.7 L233.4,51.5 L234.9,50.5 L239.6,38.7 L244.3,50.5 L245.8,51.5 L243,49.7 L248.9,62.3 L250.5,63.3 L247.7,61.5 L255.2,78 L240.9,78 L248.8,61.4 L245.9,63.2 L247.5,62.2 L253.7,49.5 L250.8,51.3 L252.4,50.3 L257.3,38.4 L262.3,50.3 L263.9,51.3 L261,49.5 L267.2,62.2 L268.8,63.2 L265.9,61.4 L273.8,78 L256.6,78 L263.4,56.9 L260.8,59.2 L262.3,58 L267.7,41.9 L265.1,44.2 L266.5,42.9 L270.8,27.9 L275.1,42.9 L276.5,44.2 L273.9,41.9 L279.3,58 L280.8,59.2 L278.2,56.9 L285,78 L273.9,78 L282.2,59.6 L279.1,61.6 L280.8,60.5 L287.4,46.4 L284.3,48.4 L286,47.3 L291.2,34.2 L296.4,47.3 L298.2,48.4 L295.1,46.4 L301.7,60.5 L303.4,61.6 L300.3,59.6 L308.6,78 L297.1,78 L305.3,58 L302.2,60.2 L303.9,59 L310.5,43.8 L307.4,45.9 L309.1,44.7 L314.3,30.4 L319.4,44.7 L321.1,45.9 L318,43.8 L324.6,59 L326.3,60.2 L323.2,58 L331.4,78 L316.9,78 L323.3,58.8 L320.9,60.9 L322.2,59.7 L327.2,45.1 L324.8,47.2 L326.2,46.1 L330.1,32.4 L334,46.1 L335.4,47.2 L333,45.1 L338,59.7 L339.3,60.9 L336.9,58.8 L343.2,78 L334.5,78 L340.3,58.5 L338.1,60.6 L339.3,59.4 L343.9,44.5 L341.8,46.6 L343,45.5 L346.6,31.5 L350.2,45.5 L351.4,46.6 L349.3,44.5 L353.8,59.4 L355.1,60.6 L352.9,58.5 L358.7,78 L345.9,78 L352.4,51.1 L350,53.9 L351.3,52.3 L356.4,31.8 L354,34.7 L355.3,33.1 L359.4,13.9 L363.4,33.1 L364.7,34.7 L362.3,31.8 L367.4,52.3 L368.8,53.9 L366.4,51.1 L372.8,78 L361.3,78 L368.1,53.7 L365.5,56.3 L366.9,54.9 L372.3,36.4 L369.8,39 L371.2,37.6 L375.5,20.2 L379.7,37.6 L381.2,39 L378.6,36.4 L384,54.9 L385.4,56.3 L382.9,53.7 L389.7,78 L382.8,78 L389.5,52.8 L387,55.5 L388.4,54 L393.7,34.7 L391.2,37.4 L392.6,35.9 L396.8,17.9 L401,35.9 L402.4,37.4 L399.9,34.7 L405.2,54 L406.6,55.5 L404.1,52.8 L410.9,78 L400.5,78 L407.5,61.1 L404.9,62.9 L406.3,61.9 L411.8,49.1 L409.2,50.9 L410.7,49.9 L415,37.8 L419.4,49.9 L420.8,50.9 L418.2,49.1 L423.7,61.9 L425.2,62.9 L422.6,61.1 L429.6,78 L423.5,78 L428,50.9 L426.3,53.8 L427.2,52.2 L430.8,31.6 L429.1,34.5 L430,32.8 L432.8,13.5 L435.6,32.8 L436.6,34.5 L434.9,31.6 L438.4,52.2 L439.4,53.8 L437.7,50.9 L442.2,78 L436.6,78 L442.1,46.7 L440,50.1 L441.2,48.2 L445.5,24.4 L443.5,27.7 L444.6,25.9 L448,3.6 L451.5,25.9 L452.6,27.7 L450.5,24.4 L454.9,48.2 L456,50.1 L454,46.7 L459.5,78 L445.8,78 L452.8,50.6 L450.1,53.5 L451.6,51.9 L457.1,31 L454.5,33.9 L456,32.3 L460.3,12.7 L464.7,32.3 L466.1,33.9 L463.5,31 L469,51.9 L470.5,53.5 L467.9,50.6 L474.9,78 L463.4,78 L469.6,52.6 L467.2,55.3 L468.5,53.8 L473.4,34.4 L471.1,37.1 L472.4,35.6 L476.3,17.4 L480.2,35.6 L481.4,37.1 L479.1,34.4 L484,53.8 L485.3,55.3 L483,52.6 L489.2,78 L476.3,78 L481.7,52.2 L479.6,55 L480.8,53.5 L485,33.8 L483,36.6 L484.1,35 L487.5,16.6 L490.8,35 L491.9,36.6 L489.9,33.8 L494.1,53.5 L495.3,55 L493.2,52.2 L498.6,78 L492.2,78 L496.9,57.9 L495.1,60.1 L496.1,58.9 L499.9,43.6 L498.1,45.7 L499.1,44.5 L502,30.2 L505,44.5 L505.9,45.7 L504.2,43.6 L507.9,58.9 L508.9,60.1 L507.1,57.9 L511.8,78 L507.2,78 L511.1,53 L509.6,55.7 L510.5,54.2 L513.5,35.2 L512.1,37.9 L512.9,36.4 L515.3,18.6 L517.7,36.4 L518.5,37.9 L517.1,35.2 L520.1,54.2 L520.9,5
3405.7 L519.5,53 L523.3,78 L515.9,78 L523.1,56.3 L520.4,58.6 L521.9,57.3 L527.6,40.7 L524.9,43.1 L526.4,41.8 L530.9,26.3 L535.4,41.8 L536.9,43.1 L534.2,40.7 L539.9,57.3 L541.4,58.6 L538.7,56.3 L545.9,78 L529.5,78 L535.7,58.1 L533.4,60.2 L534.7,59 L539.6,43.8 L537.3,46 L538.5,44.8 L542.4,30.5 L546.3,44.8 L547.6,46 L545.3,43.8 L550.2,59 L551.5,60.2 L549.1,58.1 L555.3,78 L551.3,78 L555.5,64.6 L554,66 L554.8,65.2 L558.2,55 L556.6,56.4 L557.5,55.6 L560.1,46 L562.8,55.6 L563.7,56.4 L562.1,55 L565.5,65.2 L566.3,66 L564.7,64.6 L569,78 L561.7,78 L569.5,57.1 L566.6,59.4 L568.2,58.1 L574.4,42.2 L571.5,44.5 L573.1,43.2 L578,28.3 L582.9,43.2 L584.6,44.5 L581.6,42.2 L587.8,58.1 L589.5,59.4 L586.5,57.1 L594.4,78 L589.7,78 L594.4,66.2 L592.6,67.5 L593.6,66.8 L597.3,57.8 L595.6,59.1 L596.5,58.4 L599.4,49.9 L602.3,58.4 L603.3,59.1 L601.6,57.8 L605.2,66.8 L606.2,67.5 L604.5,66.2 L609.1,78 L596.8,78 L603.2,62.9 L600.8,64.5 L602.2,63.6 L607.2,52 L604.8,53.7 L606.2,52.8 L610.2,41.9 L614.2,52.8 L615.5,53.7 L613.1,52 L618.2,63.6 L619.5,64.5 L617.1,62.9 L623.5,78 L610.9,78 L616,63 L614.1,64.6 L615.2,63.7 L619.2,52.3 L617.3,53.9 L618.4,53 L621.6,42.4 L624.8,53 L625.9,53.9 L624,52.3 L628,63.7 L629.1,64.6 L627.2,63 L632.3,78 L625.4,78 L630.9,64.3 L628.8,65.8 L630,65 L634.3,54.5 L632.2,56 L633.4,55.2 L636.8,45.4 L640.2,55.2 L641.3,56 L639.3,54.5 L643.6,65 L644.8,65.8 L642.7,64.3 L648.2,78 L638.5,78 L643.8,60.3 L641.8,62.2 L642.9,61.2 L647.1,47.7 L645.1,49.6 L646.2,48.6 L649.5,36 L652.8,48.6 L653.9,49.6 L651.9,47.7 L656.1,61.2 L657.2,62.2 L655.2,60.3 L660.5,78 L650.6,78 L656,63.6 L653.9,65.1 L655.1,64.3 L659.3,53.3 L657.3,54.9 L658.4,54 L661.8,43.7 L665.1,54 L666.2,54.9 L664.2,53.3 L668.5,64.3 L669.6,65.1 L667.6,63.6 L672.9,78 L664.8,78 L669.3,69.4 L667.6,70.4 L668.6,69.9 L672.1,63.3 L670.4,64.3 L671.4,63.7 L674.2,57.6 L676.9,63.7 L677.9,64.3 L676.2,63.3 L679.7,69.9 L680.7,70.4 L679,69.4 L683.5,78 L672.5,78 L680.2,68.9 L677.3,69.9 L678.9,69.4 L685.1,62.5 L682.2,63.5 L683.8,62.9 L688.6,56.4 L693.5,62.9 L695.1,63.5 L692.2,62.5 L698.4,69.4 L700,69.9 L697.1,68.9 L704.8,78 L695.8,78 L703.2,65.6 L700.4,66.9 L701.9,66.2 L707.8,56.8 L705,58.1 L706.5,57.3 L711.2,48.5 L715.8,57.3 L717.3,58.1 L714.5,56.8 L720.4,66.2 L721.9,66.9 L719.2,65.6 L726.6,78 L709.5,78 L716.9,70.4 L714.1,71.2 L715.6,70.8 L721.5,65 L718.7,65.8 L720.3,65.3 L724.9,59.9 L729.5,65.3 L731.1,65.8 L728.3,65 L734.2,70.8 L735.7,71.2 L732.9,70.4 L740.3,78 L729.7,78 L734,69.6 L732.4,70.5 L733.3,70 L736.7,63.6 L735.1,64.5 L736,64 L738.7,57.9 L741.4,64 L742.3,64.5 L740.6,63.6 L744.1,70 L744.9,70.5 L743.3,69.6 L747.6,78 L740.4,78 L747,68.3 L744.5,69.4 L745.9,68.8 L751.1,61.4 L748.6,62.5 L750,61.9 L754.2,55 L758.3,61.9 L759.7,62.5 L757.2,61.4 L762.4,68.8 L763.8,69.4 L761.3,68.3 L767.9,78 L756.2,78 L763.7,70.3 L760.9,71.1 L762.4,70.7 L768.4,64.8 L765.6,65.6 L767.1,65.1 L771.8,59.6 L776.5,65.1 L778.1,65.6 L775.3,64.8 L781.2,70.7 L782.8,71.1 L780,70.3 L787.5,78 L770.7,78 L777.5,71.4 L775,72.1 L776.4,71.8 L781.8,66.8 L779.2,67.5 L780.7,67.1 L784.9,62.4 L789.2,67.1 L790.6,67.5 L788.1,66.8 L793.5,71.8 L794.9,72.1 L792.4,71.4 L799.2,78 L787.6,78 L795.6,68.7 L792.6,69.7 L794.2,69.2 L800.6,62.1 L797.6,63.1 L799.2,62.6 L804.2,55.9 L809.2,62.6 L810.9,63.1 L807.9,62.1 L814.2,69.2 L815.9,69.7 L812.9,68.7 L820.9,78 L814.5,78 L820.9,71.9 L818.5,72.6 L819.9,72.2 L824.9,67.6 L822.5,68.2 L823.8,67.9 L827.8,63.5 L831.8,67.9 L833.1,68.2 L830.7,67.6 L835.8,72.2 L837.1,72.6 L834.7,71.9 L841.1,78 L832.4,78 L836.9,68.7 L835.2,69.7 L836.1,69.1 L839.7,62 L838,63 L838.9,62.5 L841.8,55.8 L844.6,62.5 L845.5,63 L843.8,62 L847.4,69.1 L848.3,69.7 L846.6,68.7 L851.1,78 L838.7,78 L847.3,68.7 L844,69.7 L845.8,69.1 L852.6,62 L849.4,63 L851.2,62.5 L856.6,55.8 L861.9,62.5 L863.7,63 L860.5,62 L867.3,69.1 L869.1,69.7 L865.9,68.7 L874.5,78 L863.6,78 L867.9,70 L866.3,70.9 L867.2,70.4 L870.6,64.3 L869,65.2 L869.9,64.7 L872.6,59 L875.3,64.7 L876.2,65.2 L874.5,64.3 L877.9,70.4 L878.8,70.9 L877.2,70 L881.5,78 L868.7,78 L877.1,71.3 L873.9,72 L875.7,71.6 L882.3,66.4 L879.2,67.2 L880.9,66.8 L886.1,61.9 L891.3,66.8 L893.1,67.2 L889.9,66.4 L896.5,71.6 L898.3,72 L895.1,71.3 L903.5,78 L887.8,78 L896.1,70.1 L893,71 L894.7,70.5 L901.3,64.5 L898.2,65.3 L899.9,64.8 L905.1,59.2 L910.3,64.8 L912.1,65.3 L908.9,64.5 L915.5,70.5 L917.3,71 L914.1,70.1 L922.5,78 L916.4,78 L920.5,69.2 L919,70.1 L919.8,69.6 L923.1,62.9 L921.6,63.9 L922.4,63.3 L925,57.1 L927.6,63.3 L928.5,63.9 L926.9,62.9 L930.2,69.6 L931,70.1 L929.5,69.2 L933.6,78 L923.1,78 L928.7,69.6 L926.6,70.5 
340L927.8,70 L932.3,63.6 L930.1,64.5 L931.3,64 L934.8,58 L938.4,64 L939.5,64.5 L937.4,63.6 L941.9,70 L943,70.5 L940.9,69.6 L946.6,78 L942.1,78 L948.1,66.2 L945.9,67.5 L947.1,66.8 L951.9,57.8 L949.6,59.1 L950.9,58.4 L954.7,50 L958.5,58.4 L959.7,59.1 L957.5,57.8 L962.2,66.8 L963.5,67.5 L961.2,66.2 L967.3,78 L954.8,78 L961.2,65.3 L958.8,66.7 L960.1,65.9 L965.2,56.3 L962.8,57.7 L964.2,56.9 L968.2,47.9 L972.2,56.9 L973.6,57.7 L971.2,56.3 L976.3,65.9 L977.6,66.7 L975.2,65.3 L981.6,78 L972.3,78 L977.6,61.4 L975.6,63.2 L976.7,62.2 L980.9,49.6 L979,51.4 L980.1,50.4 L983.4,38.6 L986.7,50.4 L987.8,51.4 L985.8,49.6 L990,62.2 L991.1,63.2 L989.1,61.4 L994.4,78 L986.1,78 L991.1,67.4 L989.3,68.5 L990.3,67.9 L994.2,59.8 L992.4,60.9 L993.4,60.3 L996.5,52.7 L999.6,60.3 L1000.7,60.9 L998.8,59.8 L1002.7,67.9 L1003.8,68.5 L1001.9,67.4 L1006.9,78 L991.5,78 L998.9,67.3 L996.1,68.4 L997.7,67.8 L1003.5,59.6 L1000.7,60.8 L1002.3,60.1 L1006.9,52.4 L1011.5,60.1 L1013.1,60.8 L1010.3,59.6 L1016.2,67.8 L1017.7,68.4 L1014.9,67.3 L1022.3,78 L1008.4,78 L1016,63.3 L1013.1,64.9 L1014.7,64 L1020.7,52.9 L1017.9,54.4 L1019.5,53.6 L1024.2,43.1 L1029,53.6 L1030.5,54.4 L1027.7,52.9 L1033.7,64 L1035.3,64.9 L1032.4,63.3 L1040,78 L1031.9,78 L1037.6,59.5 L1035.5,61.4 L1036.6,60.3 L1041.1,46.2 L1039,48.2 L1040.2,47.1 L1043.7,33.9 L1047.2,47.1 L1048.4,48.2 L1046.3,46.2 L1050.8,60.3 L1051.9,61.4 L1049.8,59.5 L1055.5,78 L1044.9,78 L1052.2,62.3 L1049.4,64 L1051,63 L1056.7,51.1 L1054,52.7 L1055.5,51.8 L1060,40.6 L1064.6,51.8 L1066.1,52.7 L1063.3,51.1 L1069.1,63 L1070.6,64 L1067.9,62.3 L1075.1,78 L1058.1,78 L1065.2,59.2 L1062.6,61.2 L1064.1,60.1 L1069.7,45.8 L1067,47.8 L1068.5,46.7 L1072.9,33.3 L1077.4,46.7 L1078.9,47.8 L1076.2,45.8 L1081.8,60.1 L1083.3,61.2 L1080.7,59.2 L1087.8,78 L1083.9,78 L1088.4,52.9 L1086.7,55.6 L1087.7,54.1 L1091.2,35 L1089.5,37.7 L1090.5,36.2 L1093.3,18.3 L1096.1,36.2 L1097,37.7 L1095.3,35 L1098.9,54.1 L1099.8,55.6 L1098.1,52.9 L1102.6,78 L1094.1,78 L1100.7,54.8 L1098.3,57.3 L1099.6,55.9 L1104.8,38.3 L1102.4,40.8 L1103.7,39.4 L1107.8,22.8 L1112,39.4 L1113.3,40.8 L1110.9,38.3 L1116.1,55.9 L1117.4,57.3 L1115,54.8 L1121.5,78 L1115.4,78 L1120.4,57.6 L1118.5,59.8 L1119.5,58.5 L1123.4,43 L1121.6,45.2 L1122.6,43.9 L1125.7,29.3 L1128.8,43.9 L1129.8,45.2 L1127.9,43 L1131.8,58.5 L1132.9,59.8 L1131,57.6 L1135.9,78 L1130.8,78 L1134.9,53.1 L1133.4,55.7 L1134.2,54.3 L1137.4,35.3 L1135.9,37.9 L1136.8,36.5 L1139.3,18.7 L1141.9,36.5 L1142.7,37.9 L1141.2,35.3 L1144.4,54.3 L1145.3,55.7 L1143.7,53.1 L1147.8,78 L1135.5,78 L1143,56.9 L1140.2,59.2 L1141.7,57.9 L1147.6,41.9 L1144.8,44.2 L1146.4,42.9 L1151,27.9 L1155.7,42.9 L1157.3,44.2 L1154.5,41.9 L1160.4,57.9 L1161.9,59.2 L1159.1,56.9 L1166.6,78 L1160.1,78 L1164.5,51.2 L1162.8,54.1 L1163.8,52.5 L1167.3,32.1 L1165.6,35 L1166.5,33.4 L1169.3,14.3 L1172.1,33.4 L1173,35 L1171.3,32.1 L1174.8,52.5 L1175.8,54.1 L1174.1,51.2 L1178.5,78 L1163.9,78 L1172.2,62.8 L1169.1,64.4 L1170.8,63.5 L1177.5,51.9 L1174.3,53.6 L1176.1,52.6 L1181.3,41.8 L1186.5,52.6 L1188.3,53.6 L1185.1,51.9 L1191.7,63.5 L1193.5,64.4 L1190.4,62.8 L1198.7,78 L1190.7,78 L1196.1,58 L1194.1,60.1 L1195.2,58.9 L1199.5,43.7 L1197.5,45.8 L1198.6,44.6 L1202,30.3 L1205.3,44.6 L1206.4,45.8 L1204.4,43.7 L1208.7,58.9 L1209.8,60.1 L1207.8,58 L1213.2,78 L1210,78 L1210,90 Z"])</script>
340<script>self.__next_f.push([1,"1d:[\"$\",\"path\",null,{\"d\":\"$1f\",\"fill\":\"currentColor\"}]\n"])</script>
340<script>self.__next_f.push([1,"1e:[\"$\",\"div\",null,{\"className\":\"relative flex flex-col text-white px-16 pb-16 pt-8 justify-center items-center text-center\",\"style\":{\"background\":\"#71222f\"},\"children\":[[\"$\",\"$L12\",null,{\"className\":\"absolute inset-0 h-full w-full\",\"mode\":\"fireflies\"}],[\"$\",\"svg\",null,{\"aria-hidden\":true,\"className\":\"absolute right-[8%] top-10 hidden -rotate-6 lg:block\",\"height\":88,\"viewBox\":\"0 0 96 96\",\"width\":88,\"children\":[[\"$\",\"defs\",null,{\"children\":[[\"$\",\"path\",null,{\"d\":\"M 15 48 A 33 33 0 0 1 81 48 A 33 33 0 0 1 15 48\",\"id\":\"ranger-badge-footer-top\"}],[\"$\",\"path\",null,{\"d\":\"M 16 48 A 32 32 0 0 0 80 48 A 32 32 0 0 0 16 48\",\"id\":\"ranger-badge-footer-bottom\"}]]}],[\"$\",\"circle\",null,{\"cx\":\"48\",\"cy\":\"48\",\"fill\":\"none\",\"r\":\"45\",\"stroke\":\"rgba(255, 240, 220, 0.75)\",\"strokeDasharray\":\"2 3\",\"strokeWidth\":\"1.5\"}],[\"$\",\"circle\",null,{\"cx\":\"48\",\"cy\":\"48\",\"fill\":\"none\",\"r\":\"22\",\"stroke\":\"rgba(255, 240, 220, 0.75)\",\"strokeWidth\":\"1\"}],[\"$\",\"text\",null,{\"fill\":\"rgba(255, 240, 220, 0.75)\",\"fontFamily\":\"var(--font-poppins), sans-serif\",\"fontSize\":\"6.5\",\"fontWeight\":\"600\",\"letterSpacing\":\"1.2\",\"children\":[\"$\",\"textPath\",null,{\"href\":\"#ranger-badge-footer-top\",\"startOffset\":\"25%\",\"textAnchor\":\"middle\",\"children\":\"CHRISTOFFER ARTMANN\"}]}],[\"$\",\"text\",null,{\"fill\":\"rgba(255, 240, 220, 0.75)\",\"fontFamily\":\"var(--font-poppins), sans-serif\",\"fontSize\":\"6.5\",\"fontWeight\":\"600\",\"letterSpacing\":\"1.2\",\"children\":[\"$\",\"textPath\",null,{\"href\":\"#ranger-badge-footer-bottom\",\"startOffset\":\"25%\",\"textAnchor\":\"middle\",\"children\":\"BARCELONA · LOOKOUT\"}]}],[\"$\",\"path\",null,{\"d\":\"M36 56 L44 43 L48.5 49.5 L52 45 L60 56 Z\",\"fill\":\"none\",\"stroke\":\"rgba(255, 240, 220, 0.75)\",\"strokeLinejoin\":\"round\",\"strokeWidth\":\"1.5\"}],[\"$\",\"circle\",null,{\"cx\":\"56\",\"cy\":\"40\",\"fill\":\"none\",\"r\":\"2.5\",\"stroke\":\"rgba(255, 240, 220, 0.75)\",\"strokeWidth\":\"1.2\"}]]}],[\"$\",\"svg\",null,{\"aria-hidden\":true,\"className\":\"absolute bottom-4 left-4 md:bottom-6 md:left-10\",\"height\":48,\"viewBox\":\"0 0 64 56\",\"width\":54.857142857142854,\"children\":[[\"$\",\"ellipse\",null,{\"className\":\"campfire-glow\",\"cx\":\"32\",\"cy\":\"44\",\"fill\":\"#f97316\",\"rx\":\"22\",\"ry\":\"10\"}],[\"$\",\"circle\",null,{\"className\":\"campfire-spark\",\"cx\":\"26\",\"cy\":\"24\",\"fill\":\"#fbbf24\",\"r\":\"1\"}],[\"$\",\"circle\",null,{\"className\":\"campfire-spark\",\"cx\":\"39\",\"cy\":\"28\",\"fill\":\"#fcd34d\",\"r\":\"0.8\",\"style\":{\"animationDelay\":\"-1.4s\"}}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-outer\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 12 C38 22 43 30 43 38 C43 45 38 49 32 49 C26 49 21 45 21 38 C21 30 26 22 32 12 Z\",\"fill\":\"#f59e0b\"}]}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-mid\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 20 C36 27 39.5 32 39.5 38 C39.5 43.5 36 46.5 32 46.5 C28 46.5 24.5 43.5 24.5 38 C24.5 32 28 27 32 20 Z\",\"fill\":\"#f97316\"}]}],[\"$\",\"g\",null,{\"className\":\"campfire-flame-inner\",\"children\":[\"$\",\"path\",null,{\"d\":\"M32 29 C34.5 33.5 36 36.5 36 40 C36 43.5 34 45 32 45 C30 45 28 43.5 28 40 C28 36.5 29.5 33.5 32 29 Z\",\"fill\":\"#fde68a\"}]}],[\"$\",\"rect\",null,{\"fill\":\"#8a5a3b\",\"height\":\"5\",\"rx\":\"2.5\",\"transform\":\"rotate(14 32 48.5)\",\"width\":\"26\",\"x\":\"19\",\"y\":\"46\"}],[\"$\",\"rect\",null,{\"fill\":\"#6f4530\",\"height\":\"5\",\"rx\":\"2.5\",\"transform\":\"rotate(-14 32 48.5)\",\"width\":\"26\",\"x\":\"19\",\"y\":\"46\"}]]}],[\"$\",\"div\",null,{\"className\":\"relative z-10 flex flex-col items-center\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex-shrink-0 mb-4\",\"children\":[\"$\",\"img\",null,{\"alt\":\"Christoffer Artmann\",\"className\":\"w-16 h-16 rounded-full shadow-lg md:w-24 md:h-24\",\"src\":\"/images/christoffer-artmann.jpg\"}]}],[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center gap-2\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"text-xl m-0 text-white\",\"children\":\"Hi, I'm Chris!\"}],[\"$\",\"p\",null,{\"className\":\"text-sm m-0\",\"children\":\"I'm a Software Engineer and Product Manager living in sunny Barcelona.\"}],[\"$\",\"p\",null,{\"className\":\"text-sm m-0\",\"children\":\"If you want to chat, you can find me on all the social platforms.\"}],[\"$\",\"div\",null,{\"className\":\"flex gap-4 mt-4 text-2xl justify-center items-center\",\"children\":[[\"$\",\"a\",\"0\",{\"href\":\"https://github.com/artmann/\",\"children\":[\"$\",\"svg\",null,{\"stroke\":\"currentColor\",\"fill\":\"none\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"children\":[\"$undefined\",[[\"$\",\"path\",\"0\",{\"d\":\"M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22\",\"children\":[]}]]],\"className\":\"$undefined\",\"style\":{\"color\":\"$undefined\"}
340,\"height\":\"1em\",\"width\":\"1em\",\"xmlns\":\"http://www.w3.org/2000/svg\"}]}],\"$L20\",\"$L21\",\"$L22\",\"$L23\"]}]]}]]}]]}]\n"])</script>
340<script>self.__next_f.push([1,"20:[\"$\",\"a\",\"1\",{\"href\":\"https://www.instagram.com/christofferartmann/\",\"children\":[\"$\",\"svg\",null,{\"stroke\":\"currentColor\",\"fill\":\"none\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"children\":[\"$undefined\",[[\"$\",\"rect\",\"0\",{\"x\":\"2\",\"y\":\"2\",\"width\":\"20\",\"height\":\"20\",\"rx\":\"5\",\"ry\":\"5\",\"children\":[]}],[\"$\",\"path\",\"1\",{\"d\":\"M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z\",\"children\":[]}],[\"$\",\"line\",\"2\",{\"x1\":\"17.5\",\"y1\":\"6.5\",\"x2\":\"17.51\",\"y2\":\"6.5\",\"children\":[]}]]],\"className\":\"$undefined\",\"style\":{\"color\":\"$undefined\"},\"height\":\"1em\",\"width\":\"1em\",\"xmlns\":\"http://www.w3.org/2000/svg\"}]}]\n21:[\"$\",\"a\",\"2\",{\"href\":\"https://www.linkedin.com/in/chistoffer-artmann\",\"children\":[\"$\",\"svg\",null,{\"stroke\":\"currentColor\",\"fill\":\"none\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"children\":[\"$undefined\",[[\"$\",\"path\",\"0\",{\"d\":\"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z\",\"children\":[]}],[\"$\",\"rect\",\"1\",{\"x\":\"2\",\"y\":\"9\",\"width\":\"4\",\"height\":\"12\",\"children\":[]}],[\"$\",\"circle\",\"2\",{\"cx\":\"4\",\"cy\":\"4\",\"r\":\"2\",\"children\":[]}]]],\"className\":\"$undefined\",\"style\":{\"color\":\"$undefined\"},\"height\":\"1em\",\"width\":\"1em\",\"xmlns\":\"http://www.w3.org/2000/svg\"}]}]\n22:[\"$\",\"a\",\"3\",{\"href\":\"https://twitter.com/chrisartmann\",\"children\":[\"$\",\"svg\",null,{\"stroke\":\"currentColor\",\"fill\":\"none\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"children\":[\"$undefined\",[[\"$\",\"path\",\"0\",{\"d\":\"M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z\",\"children\":[]}]]],\"className\":\"$undefined\",\"style\":{\"color\":\"$undefined\"},\"height\":\"1em\",\"width\":\"1em\",\"xmlns\":\"http://www.w3.org/2000/svg\"}]}]\n23:[\"$\",\"a\",\"4\",{\"href\":\"https://linktr.ee/chrisartmann\",\"children\":[\"$\",\"svg\",null,{\"stroke\":\"currentColor\",\"fill\":\"none\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"children\":[\"$undefined\",[[\"$\",\"path\",\"0\",{\"d\":\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\",\"children\":[]}],[\"$\",\"path\",\"1\",{\"d\":\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\",\"children\":[]}]]],\"className\":\"$undefined\",\"style\":{\"color\":\"$undefined\"},\"height\":\"1em\",\"width\":\"1em\",\"xmlns\":\"http://www.w3.org/2000/svg\"}]}]\n"])</script>
340</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.