<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Juno Blog</title>
        <link>https://juno.build/blog</link>
        <description>Juno Blog</description>
        <lastBuildDate>Sun, 05 Apr 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[HTTP Requests in TypeScript Serverless Functions]]></title>
            <link>https://juno.build/blog/http-requests-typescript-serverless-functions</link>
            <guid>https://juno.build/blog/http-requests-typescript-serverless-functions</guid>
            <pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[One of the most requested features for TypeScript serverless functions has always been the ability to make HTTP requests to external APIs.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/http-requests-typescript-serverless-functions-548b19a5c5103a1c7d99e6018a74ecea.png" width="1600" height="980" class="img_ev3q"></p>
<p>One of the most requested features for TypeScript serverless functions has always been the ability to make HTTP requests to external APIs.</p>
<p>That's now supported 🚀.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="http-requests">HTTP Requests<a href="https://juno.build/blog/http-requests-typescript-serverless-functions#http-requests" class="hash-link" aria-label="Direct link to HTTP Requests" title="Direct link to HTTP Requests" translate="no">​</a></h2>
<p>Rust serverless functions have been able to reach out to the outside world via HTTPS for a while. That comes naturally since Rust functions leverage the <code>ic_cdk</code>, which is maintained by the DFINITY foundation for the Internet Computer and therefore, supports it out of the box.</p>
<p>On the other hand, TypeScript serverless functions are unique to Juno, so features are added incrementally.</p>
<p>Performing those kind of requests happens through a feature called HTTPS outcalls. Using it, you can extend your Satellite to fetch data, trigger webhooks, call third-party services, whatever your use case requires. In Juno's own codebase, it is used to send emails and fetch the public keys of the OpenID providers supported for authentication.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="making-a-request">Making a Request<a href="https://juno.build/blog/http-requests-typescript-serverless-functions#making-a-request" class="hash-link" aria-label="Direct link to Making a Request" title="Direct link to Making a Request" translate="no">​</a></h2>
<p>Here's a simple example using the <a href="https://dog.ceo/dog-api/" target="_blank" rel="noopener noreferrer">Dog CEO API<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> to fetch a random dog image URL and return it directly from an update function:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineUpdate </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> httpRequest</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">type</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">HttpRequestArgs</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions/ic-cdk"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> j </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/schema"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> DogSchema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  message</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  status</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> fetchRandomDog </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineUpdate</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  result</span><span class="token operator" style="color:white">:</span><span class="token plain"> DogSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> args</span><span class="token operator" style="color:white">:</span><span class="token plain"> HttpRequestArgs </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      url</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"https://dog.ceo/api/breeds/image/random"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      method</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"GET"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      isReplicated</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token boolean" style="color:white">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> result </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">httpRequest</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> decoder </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">new</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">TextDecoder</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> body </span><span class="token operator" style="color:white">=</span><span class="token plain"> decoder</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">decode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">body</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">return</span><span class="token plain"> </span><span class="token constant" style="color:white">JSON</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">parse</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Define the function, call the API, use the result. That's it.</p>
<p><img decoding="async" loading="lazy" alt="Magic GIF for fun" src="https://juno.build/assets/images/magical-magic-cfcd3e898ab0235aae315734fd238b35.gif" width="274" height="252" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="transformer">Transformer<a href="https://juno.build/blog/http-requests-typescript-serverless-functions#transformer" class="hash-link" aria-label="Direct link to Transformer" title="Direct link to Transformer" translate="no">​</a></h2>
<p>Some APIs return response headers that vary between nodes, timestamps, request IDs, and so on. In replicated mode, where the request is run multiple times and reconciled to ensure its validity, this can cause the call to fail if all responses do not match.</p>
<p>To handle this, you can define a transform function that sanitizes the response before the nodes compare it. A common pattern is to strip the headers entirely:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> defineUpdate </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  httpRequest</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  HttpRequestResultSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  TransformArgsSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword" style="color:#b0baff">type</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">HttpRequestArgs</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions/ic-cdk"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> j </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/schema"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> DogSchema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  message</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  status</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> fetchRandomDog </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineUpdate</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  result</span><span class="token operator" style="color:white">:</span><span class="token plain"> DogSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> args</span><span class="token operator" style="color:white">:</span><span class="token plain"> HttpRequestArgs </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      url</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"https://dog.ceo/api/breeds/image/random"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      method</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"GET"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      isReplicated</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token boolean" style="color:white">true</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      transform</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"trimHeaders"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> result </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">httpRequest</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> decoder </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">new</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">TextDecoder</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> body </span><span class="token operator" style="color:white">=</span><span class="token plain"> decoder</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">decode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">body</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">return</span><span class="token plain"> </span><span class="token constant" style="color:white">JSON</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">parse</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> trimHeaders </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  hidden</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token boolean" style="color:white">true</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  args</span><span class="token operator" style="color:white">:</span><span class="token plain"> TransformArgsSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  result</span><span class="token operator" style="color:white">:</span><span class="token plain"> HttpRequestResultSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> response</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> status</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> body </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    status</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    body</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    headers</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>The <code>transform</code> field references the name of an exported query function. Marking it <code>hidden: true</code> keeps it out of the auto-generated client API, it's an implementation detail, not something you'd call from the frontend.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="guards">Guards<a href="https://juno.build/blog/http-requests-typescript-serverless-functions#guards" class="hash-link" aria-label="Direct link to Guards" title="Direct link to Guards" translate="no">​</a></h2>
<p>This release also ships support for guards that let you protect your functions with access control logic, restricting who can call them before the handler even runs.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineQuery </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> callerIsAdmin </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions/sdk"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> ping </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">guard</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">new</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">Error</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"No pong today"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"Hello"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> hello </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  guard</span><span class="token operator" style="color:white">:</span><span class="token plain"> callerIsAdmin</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"Hello, admin!"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="references">References<a href="https://juno.build/blog/http-requests-typescript-serverless-functions#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h2>
<p>Following sections of the documentation have been updated:</p>
<ul>
<li class=""><a href="https://juno.build/docs/guides/typescript#https-outcalls">Guides</a></li>
<li class=""><a href="https://juno.build/docs/reference/functions/typescript/ic-cdk#httprequest">References</a></li>
</ul>
<hr>
<p>HTTP requests were a feature often requested and led a few developers to choose Rust for that reason. Really happy to finally ship this one and hopefully see more devs embrace the simplicity of using TypeScript.</p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>functions</category>
            <category>typescript</category>
            <category>sputnik</category>
            <category>serverless</category>
            <category>fetch</category>
            <category>api</category>
        </item>
        <item>
            <title><![CDATA[Custom Functions in TypeScript]]></title>
            <link>https://juno.build/blog/custom-functions-in-typescript</link>
            <guid>https://juno.build/blog/custom-functions-in-typescript</guid>
            <pubDate>Mon, 16 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The idea behind Juno's serverless functions is that you should be able to write them in either Rust or TypeScript following the same pattern and mental model. Parts of those, hooks, have been available in TypeScript for a while and are handy for reacting to events. But developers also often want to define their own functions, akin to adding custom endpoints to an HTTP API. That wasn't supported in TypeScript, until now 🚀.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/custom-functions-in-typescript-snippet-11baea283d0c73597d0f4a159eb4ad7d.png" width="1600" height="946" class="img_ev3q"></p>
<p>The idea behind Juno's serverless functions is that you should be able to write them in either Rust or TypeScript following the same pattern and mental model. Parts of those, hooks, have been available in TypeScript for a while and are handy for reacting to events. But developers also often want to define their own functions, akin to adding custom endpoints to an HTTP API. That wasn't supported in TypeScript, until now 🚀.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="custom-functions">Custom Functions<a href="https://juno.build/blog/custom-functions-in-typescript#custom-functions" class="hash-link" aria-label="Direct link to Custom Functions" title="Direct link to Custom Functions" translate="no">​</a></h2>
<p>Custom functions let you define callable endpoints directly inside your Satellite, which can be explicitly invoked from your frontend or from other services.</p>
<p>There are two kinds.</p>
<p>A <strong>query</strong> is read-only. It returns data without touching any state, and it's fast. Use it when you just need to fetch something.</p>
<p>An <strong>update</strong> can read and write. Use it when your logic needs to persist data, trigger side effects, or when you need an absolute tamper-proof guarantee on the result.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineQuery </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> ping </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"pong"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>The functions can be described with optional arguments and results. They are strongly typed both at runtime and at build time thanks to a new type system, and their handlers can be synchronous or asynchronous.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineUpdate </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> j </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/schema"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> ArgsSchema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  name</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> ResultSchema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  message</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> myUpdate </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineUpdate</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  args</span><span class="token operator" style="color:white">:</span><span class="token plain"> ArgsSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  result</span><span class="token operator" style="color:white">:</span><span class="token plain"> ResultSchema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> name </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token comment" style="color:#707070;font-style:italic">// your logic here</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">return</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> message</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#b0baff">`</span><span class="token template-string string" style="color:#b0baff">Saved </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:hsl(220, 14%, 71%)">${</span><span class="token template-string interpolation">name</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token template-string string" style="color:#b0baff">.</span><span class="token template-string template-punctuation string" style="color:#b0baff">`</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="auto-generated-bindings">Auto-generated Bindings<a href="https://juno.build/blog/custom-functions-in-typescript#auto-generated-bindings" class="hash-link" aria-label="Direct link to Auto-generated Bindings" title="Direct link to Auto-generated Bindings" translate="no">​</a></h2>
<p>Another part that makes this genuinely fun to use: when you build your project, a type-safe client API is automatically generated based on your function definitions. No glue code, no manual wiring, no thinking about serialization. Your functions are simply available through the <code>functions</code> namespace.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> functions </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"../declarations/satellite/satellite.api.ts"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> functions</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">ping</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> functions</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">myUpdate</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> name</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"David"</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Define the shape on the backend, call it from the frontend with full type safety. That's it.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="schema-types">Schema Types<a href="https://juno.build/blog/custom-functions-in-typescript#schema-types" class="hash-link" aria-label="Direct link to Schema Types" title="Direct link to Schema Types" translate="no">​</a></h2>
<p>Arguments and return types are optional, but when you need them, Juno provides a type system built on top of <a href="https://zod.dev/" target="_blank" rel="noopener noreferrer">Zod<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> to let you define their shapes.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> j </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/schema"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Those schemas are validated at runtime and used at build time to generate all the necessary bindings. You define the shape once, you get safety everywhere.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> Schema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  name</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  age</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">number</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Since you will likely need some environment-specific types, <code>j</code> extends Zod with <code>j.principal()</code> and <code>j.uint8array()</code>.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> Schema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  owner</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">principal</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  data</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">uint8array</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>And when your function needs to handle multiple distinct input shapes, reach for <code>discriminatedUnion</code>:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineUpdate </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> j </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/schema"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> Schema </span><span class="token operator" style="color:white">=</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">discriminatedUnion</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"type"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> type</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">literal</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"cat"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> indoor</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">boolean</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">strictObject</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> type</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">literal</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"dog"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> breed</span><span class="token operator" style="color:white">:</span><span class="token plain"> j</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> registerPet </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineUpdate</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  args</span><span class="token operator" style="color:white">:</span><span class="token plain"> Schema</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">handler</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> args </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">type </span><span class="token operator" style="color:white">===</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"cat"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token comment" style="color:#707070;font-style:italic">// handle cat</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">else</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token comment" style="color:#707070;font-style:italic">// handle dog</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Long story short, <code>j</code> is Zod with a few extras and everything you need to strongly type your functions.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="references">References<a href="https://juno.build/blog/custom-functions-in-typescript#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h2>
<p>Following sections of the documentation have been updated:</p>
<ul>
<li class=""><a href="https://juno.build/docs/build/functions/development/">Development</a></li>
<li class=""><a href="https://juno.build/docs/guides/typescript">Guides</a></li>
<li class=""><a href="https://juno.build/docs/reference/functions/typescript">References (SDK, schema, etc.)</a></li>
</ul>
<hr>
<p>I'm genuinely excited about these improvements and can totally see myself not using Rust for writing serverless functions in most of my projects in a near future. Not entirely there yet, HTTPS outcalls support in TypeScript is still coming, but getting there.</p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>functions</category>
            <category>typescript</category>
            <category>sputnik</category>
            <category>serverless</category>
        </item>
        <item>
            <title><![CDATA[GitHub Automation and Authentication]]></title>
            <link>https://juno.build/blog/github-automation-and-authentication</link>
            <guid>https://juno.build/blog/github-automation-and-authentication</guid>
            <pubDate>Thu, 19 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Like it or not, GitHub is where most developers already live - it's where code is written, reviewed, and shipped with or without AI. So rather than asking you to adapt your workflow to Juno, I've been working on bringing Juno closer to yours.]]></description>
            <content:encoded><![CDATA[<p>Like it or not, GitHub is where most developers already live - it's where code is written, reviewed, and shipped with or without AI. So rather than asking you to adapt your workflow to Juno, I've been working on bringing Juno closer to yours.</p>
<p>Two new features ship in that direction: a new recommended approach for automating deployments via GitHub Actions, and support for GitHub authentication in your applications 🚀.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="automation-without-secrets">Automation Without Secrets<a href="https://juno.build/blog/github-automation-and-authentication#automation-without-secrets" class="hash-link" aria-label="Direct link to Automation Without Secrets" title="Direct link to Automation Without Secrets" translate="no">​</a></h2>
<p>Until now, setting up GitHub Actions to deploy your frontend or publish serverless functions required storing a <code>JUNO_TOKEN</code> in your GitHub secrets. It worked, but it came with the usual headaches, tokens to generate, rotate, and keep out of the wrong hands.</p>
<p>The new recommended approach uses OpenID Connect (OIDC). Instead of a static token, GitHub and your Satellite establish a trust relationship, and each workflow run gets short-lived credentials (access keys) automatically. Once the run is done, the credentials are gone.</p>
<p>No tokens to rotate. No secrets to manage. And if a workflow is ever compromised, there's nothing long-lived to steal.</p>
<p>To support this, a new <strong>Deployments</strong> screen has been added to the Console. This is where you configure which repositories are allowed to deploy to your Satellite and where you can review past deployments.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>Obviously and as always, you can also configure the same options with your CLI if you prefer.</p></div></div>
<p>👉 <a href="https://juno.build/docs/guides/github-actions/">Documentation</a></p>
<p><img decoding="async" loading="lazy" alt="The new Deployments screen in the Juno Console, listing GitHub Actions workflow" src="https://juno.build/assets/images/console-deployments-workflows-ea52a9fba9f5e4b25e12e84e393d4844.png" width="1640" height="1141" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="github-authentication">GitHub Authentication<a href="https://juno.build/blog/github-automation-and-authentication#github-authentication" class="hash-link" aria-label="Direct link to GitHub Authentication" title="Direct link to GitHub Authentication" translate="no">​</a></h2>
<p>You can now add GitHub authentication to your application, letting your users sign in with their GitHub account, a natural fit for developer-facing apps.</p>
<p>Unlike other providers, GitHub does not natively support OpenID Connect. That's why this authentication requires a small proxy that handles the OAuth exchange securely to avoid exposing a client secret directly within your Satellite.</p>
<p>Juno provides an open-source API for this: <a href="https://github.com/junobuild/api" target="_blank" rel="noopener noreferrer">github.com/junobuild/api<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>. You self-host it, point your configuration to it, and from there the flow is straightforward, the user signs in, the proxy issues a JWT, your Satellite verifies it, and a session is created.</p>
<p>One thing to be aware of though: because the proxy signs JWTs with RSA keys, your Satellite needs access to those public keys to verify them. Rather than having each Satellite make HTTPS outcalls to your proxy on every request, Juno uses a shared infrastructure module called Observatory to fetch and cache those keys. Since you're self-hosting the proxy, you'll also need to deploy your own Observatory instance and configure it to point to your proxy's JWKS endpoint.</p>
<p>It's a bit tricky to set up but worth the effort if you're targeting developers. Reach out if you have questions, always happy to help!</p>
<p>👉 <a href="https://juno.build/docs/build/authentication/github">Documentation</a></p>
<hr>
<p>One could argue that instead of improving the integration with GitHub, I should spin up custom infrastructure and provide the entire CI/CD for building and deploying. I wouldn't disagree. If the goal were to compete with cloud providers like AWS, Vercel, you name it, that would probably be the path. But devops is not really my thing, and that would be quite an effort both in terms of development and maintenance for the sole developer I am, who already takes care of a gigantic codebase 😅. Maybe someday, but honestly it feels unlikely as I doubt Juno will ever become a company.</p>
<p>Until then, I think this is a great step in the right direction - a tighter integration between Juno and the tools you already use day to day. Hope you find it useful too!</p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>github</category>
            <category>authentication</category>
            <category>automation</category>
            <category>github actions</category>
            <category>workflows</category>
        </item>
        <item>
            <title><![CDATA[Architecture Changes for a Better Developer Experience]]></title>
            <link>https://juno.build/blog/architecture-changes-for-better-developer-experience</link>
            <guid>https://juno.build/blog/architecture-changes-for-better-developer-experience</guid>
            <pubDate>Thu, 08 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Happy New Year 🥳]]></description>
            <content:encoded><![CDATA[<p>Happy New Year 🥳</p>
<p>We're kicking off 2026 with a major <a href="https://github.com/junobuild/juno/releases/tag/v0.0.63" target="_blank" rel="noopener noreferrer">release<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> that ships significant changes in the architecture and design of the Juno Console with a single goal: making the DX more straightforward and comprehensive.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="mission-control-and-monitoring-merged">Mission Control and Monitoring merged<a href="https://juno.build/blog/architecture-changes-for-better-developer-experience#mission-control-and-monitoring-merged" class="hash-link" aria-label="Direct link to Mission Control and Monitoring merged" title="Direct link to Mission Control and Monitoring merged" translate="no">​</a></h2>
<p>Mission Control was originally designed as a dedicated control center for developers — a place to create and manage projects (Satellites) and analytics (Orbiters). Over time, it was also extended to include Monitoring.</p>
<p>The original idea was simple: the Console would only know a developer's identity and their Mission Control ID — nothing else.</p>
<p>While this approach had advantages, it also introduced significant drawbacks.</p>
<p>On every new sign-up, the Console had to automatically create a Mission Control. This meant that when a developer signed in and created their first (free) project, Juno had to provision <strong>two containers instead of one</strong>, increasing infrastructure costs.</p>
<p>It also led to a confusing user experience. Mission Control could not be hidden from the UI because modules must be provisioned with resources (cycles) to avoid being decommissioned. As a result, it was always visible, and many developers were unsure what Mission Control was or why it existed.</p>
<p>For these reasons, Mission Control and Monitoring have now been merged:</p>
<ul>
<li class="">A Mission Control is created <strong>only when a developer explicitly enables Monitoring</strong></li>
<li class="">Monitoring is now treated as a dedicated microservice</li>
</ul>
<p>This architectural change brings clear benefits:</p>
<ul>
<li class=""><strong>For developers:</strong> a clearer, more straightforward experience and simpler long-term maintenance</li>
<li class=""><strong>For Juno:</strong> acquisition costs for new developers are effectively cut in half</li>
</ul>
<p>There are a few trade-offs to note:</p>
<ul>
<li class="">The Juno Console now keeps track of all containers created by developers (Satellites, Orbiters, and Mission Controls), whereas previously it only knew the Mission Control ID.</li>
<li class="">When Monitoring is enabled, module metadata must be duplicated inside the Mission Control so it knows what to monitor. This introduces a risk of inconsistencies if a bug causes a mismatch between the Console and Monitoring data. To mitigate this, a Console feature is planned to compare and verify this information.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="deprecate-icp-use-only-cycles">Deprecate ICP, use only Cycles<a href="https://juno.build/blog/architecture-changes-for-better-developer-experience#deprecate-icp-use-only-cycles" class="hash-link" aria-label="Direct link to Deprecate ICP, use only Cycles" title="Direct link to Deprecate ICP, use only Cycles" translate="no">​</a></h2>
<p>Over the past year, I've been refining both the platform and its communication to reinforce Juno's vision: a platform to build, deploy, and run applications in WASM containers, with ownership and zero DevOps.</p>
<p>As part of this effort, I've aimed to remove all blockchain and crypto-slangs.</p>
<p>While merging Mission Control and Monitoring, a new wallet ID - derived from the developer's sign-in - had to be introduced.</p>
<p>During this work, it became really clear again that the onboarding for new developers was just confusing:</p>
<blockquote>
<p>Why do I need ICP to get cycles?</p>
</blockquote>
<p>Since this release already introduced breaking changes, it felt like the right moment to simplify the model further.</p>
<p>As a result, <strong>ICP is now deprecated in favor of using cycles only</strong>.</p>
<p>This significantly simplifies the user journey:</p>
<ul>
<li class="">You start using Juno for free</li>
<li class="">You learn about cycles as the resource that powers your containers and services</li>
<li class="">When you need more resources or want to spin up additional modules, you acquire cycles</li>
</ul>
<p>To support this, the primary call to action for acquiring cycles now points to <a href="https://cycle.express/" target="_blank" rel="noopener noreferrer">cycle.express<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>, which allows developers to convert dollars directly into cycles. Third-party wallets like <a href="https://oisy.com/" target="_blank" rel="noopener noreferrer">OISY<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> remain supported, but are now positioned as secondary options for users already familiar with them.</p>
<p>Together with the other changes in this release, this should make both the developer experience and the mental model of how Juno works much more approachable.</p>
<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/cycles-everywhere-1288ab405da3f3ce94e77e1d254e74a7.png" width="640" height="435" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="price-increase">Price increase<a href="https://juno.build/blog/architecture-changes-for-better-developer-experience#price-increase" class="hash-link" aria-label="Direct link to Price increase" title="Direct link to Price increase" translate="no">​</a></h2>
<p>Previously, creating new Satellites or Orbiters cost 0.4 ICP. In practice, this was undervalued: each module is provisioned with 1.5 T cycles, while 0.4 ICP corresponds to roughly 0.93 T cycles—effectively a significant bonus.</p>
<p>Going forward:</p>
<ul>
<li class="">Additional Satellites and Orbiters cost 3 T cycles (roughly $4).</li>
<li class="">Enabling Monitoring (which spins up a Mission Control) requires the same fee.</li>
</ul>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>See the <a href="https://juno.build/docs/pricing">Pricing</a> documentation for more details.</p></div></div>
<hr>
<p>I believe these changes represent a significant step forward in making Juno more accessible and easier to understand. Whether you're just getting started or have been with us for a while, I hope these improvements make your development experience that much better.</p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>architecture</category>
            <category>dx</category>
            <category>platform</category>
        </item>
        <item>
            <title><![CDATA[Juno is now fully open-source]]></title>
            <link>https://juno.build/blog/juno-is-now-fully-open-source</link>
            <guid>https://juno.build/blog/juno-is-now-fully-open-source</guid>
            <pubDate>Wed, 24 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey 👋]]></description>
            <content:encoded><![CDATA[<p>Hey 👋</p>
<p>Juno is now fully open-source. No more AGPL. The project is now entirely released under the MIT license.</p>
<p>While all the tools were already licensed under MIT, the platform itself, a few crates, and the documentation were still released under AGPL. That worked well in the early days but can create friction for those who want to reuse Juno, or parts of it, in commercial projects or corporate environments. Plus, AGPL is not that cool, no? 😎</p>
<p>You can also consider this a small Christmas gift 🎁😉</p>
<p>Thank you to everyone who followed, tested, used, and supported Juno this year. I wish you a Merry Christmas and a fantastic New Year 2026.</p>
<p>You can find the source code on GitHub:
👉 <a href="https://github.com/junobuild/juno" target="_blank" rel="noopener noreferrer">https://github.com/junobuild/juno<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>
<p>Merry Christmas from Zürich 🎄<br>David</p>]]></content:encoded>
            <category>open-source</category>
            <category>mit</category>
            <category>licensing</category>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Serverless Canister Calls in TypeScript]]></title>
            <link>https://juno.build/blog/typescript-serverless-canister-calls</link>
            <guid>https://juno.build/blog/typescript-serverless-canister-calls</guid>
            <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey 👋]]></description>
            <content:encoded><![CDATA[<p>Hey 👋</p>
<p>If you like working with <a href="https://github.com/dfinity/icp-js-canisters" target="_blank" rel="noopener noreferrer">ic-js<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> in the frontend...<br>
<!-- -->Say hello to <strong>serverless canister functions in TypeScript</strong> ⚡️</p>
<p>Write backend logic using the same TypeScript you already love — now with:</p>
<ul>
<li class="">💫 Built-in canister clients for the Internet Computer (ICP, ICRC, CMC, NNS, SNS...)</li>
<li class="">⚙️ Full type-safety</li>
<li class="">🔌 Zero agent setup</li>
<li class="">🧠 Caller identity handled automatically</li>
<li class="">🍱 ICP &amp; ICRC transfers from serverless hooks</li>
</ul>
<p>No Rust required. No backend headaches.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-documentation">📚 Documentation<a href="https://juno.build/blog/typescript-serverless-canister-calls#-documentation" class="hash-link" aria-label="Direct link to 📚 Documentation" title="Direct link to 📚 Documentation" translate="no">​</a></h2>
<p>Want to go straight to the point? Checkout the 👉 <a href="https://juno.build/docs/reference/functions/typescript/canisters">references</a></p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="example">Example<a href="https://juno.build/blog/typescript-serverless-canister-calls#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no">​</a></h2>
<p>Transfer ICP directly from a Satellite serverless function:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> IcpLedgerCanister </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/functions/canisters/ledger/icp"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#ff5df9">onExecute</span><span class="token plain"> </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> ledger </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">new</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">IcpLedgerCanister</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> result </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> ledger</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">transfer</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    args</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      to</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"destination-account-identifier"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      amount</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> e8s</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token number" style="color:white">100_000_000n</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token comment" style="color:#707070;font-style:italic">// 1 ICP</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      fee</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> e8s</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token number" style="color:white">10_000n</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      memo</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token number" style="color:white">0n</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>And yes - this works inside datastore hooks like <code>onSetDoc</code> and <code>assertSetDoc</code>, fully atomic.</p>
<p>Browse the full working example 👉 <a href="https://juno.build/docs/examples/functions/typescript/canister-calls">Making Canister Calls in TypeScript</a></p>
<p>Cool cool cool?</p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>release</category>
            <category>serverless</category>
            <category>typescript</category>
            <category>canisters</category>
            <category>icp</category>
            <category>icrc</category>
            <category>sdk</category>
        </item>
        <item>
            <title><![CDATA[Custom Domains Support Upgrade]]></title>
            <link>https://juno.build/blog/2025-10-20-custom-domains-support-upgrade</link>
            <guid>https://juno.build/blog/2025-10-20-custom-domains-support-upgrade</guid>
            <pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey 👋]]></description>
            <content:encoded><![CDATA[<p>Hey 👋</p>
<p>A new <a href="https://github.com/junobuild/juno/releases/tag/v0.0.60" target="_blank" rel="noopener noreferrer">release<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> was shipped with two sweet improvements to the <a href="https://console.juno.build/" target="_blank" rel="noopener noreferrer">Console<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>.</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-custom-domains-new-api">🌐 Custom Domains New API<a href="https://juno.build/blog/2025-10-20-custom-domains-support-upgrade#-custom-domains-new-api" class="hash-link" aria-label="Direct link to 🌐 Custom Domains New API" title="Direct link to 🌐 Custom Domains New API" translate="no">​</a></h2>
<p>The hosting features for registering or administrating custom domains have been migrated to the API from the <a href="https://dfinity.org/" target="_blank" rel="noopener noreferrer">DFINITY<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> Boundary Nodes team.</p>
<p>This migration makes managing domains:</p>
<ul>
<li class="">More reliable</li>
<li class="">Significantly faster</li>
<li class="">Future-proof</li>
</ul>
<p>Massive kudos to the team delivering this capability - awesome work 💪</p>
<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">🚀 Registering custom domains for your hosting just got a major upgrade!<br><br>The new API is more reliable, faster, and future-proof. <br><br>Shout-out to the awesome <a href="https://twitter.com/dfinity?ref_src=twsrc%5Etfw">@dfinity</a> Boundary Nodes team 💪 <a href="https://t.co/MSPC81AOoc">pic.twitter.com/MSPC81AOoc</a></p>— Juno (@junobuild) <a href="https://twitter.com/junobuild/status/1991222201320698117?ref_src=twsrc%5Etfw">November 19, 2025</a></blockquote>
<!-- -->
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-ui-improvements">✨ UI Improvements<a href="https://juno.build/blog/2025-10-20-custom-domains-support-upgrade#-ui-improvements" class="hash-link" aria-label="Direct link to ✨ UI Improvements" title="Direct link to ✨ UI Improvements" translate="no">​</a></h2>
<p>Alongside the domain upgrade, we shipped a few visual refinements:</p>
<p>Stronger contrast on cards and buttons for a cleaner, more readable interface (amazing what you can achieve by nudging brightness 😄)</p>
<p>The Launchpad has been slightly redesigned: "Create a new satellite" is now a primary button, bringing more clarity and guidance.</p>
<p><img decoding="async" loading="lazy" src="https://github.com/user-attachments/assets/45e30096-d779-4a81-96f2-e9baf518c66e" alt="A screenshot of the launchpad that showcases the new contrast and actions that have been moved" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://github.com/user-attachments/assets/b2e93943-4082-43a6-828f-d856a35fba68" alt="Another screenshots from the authentication setup which displays the new tabs design" class="img_ev3q"></p>
<p>To infinity and beyond<br>David</p>]]></content:encoded>
            <category>release</category>
            <category>hosting</category>
            <category>custom domain</category>
            <category>ui</category>
            <category>console</category>
            <category>frontend</category>
        </item>
        <item>
            <title><![CDATA[Google Sign-In Comes to Juno]]></title>
            <link>https://juno.build/blog/google-sign-in-comes-to-juno</link>
            <guid>https://juno.build/blog/google-sign-in-comes-to-juno</guid>
            <pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Google Sign-In is now available across the entire Juno ecosystem - for developers and for the apps they build.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/all-hail-to-do-not-be-evil-673e40ac0b2363c66c4015b00d038d84.webp" width="1200" height="800" class="img_ev3q"></p>
<hr>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><p>You can now use your Google account to log into the Juno Console, and developers can add the same familiar login experience natively to the projects they are building.</p></div></div>
<p>Hey everyone 👋</p>
<p>Today marks quite a milestone and I'm excited to share that Google Sign-In is now live across the entire Juno ecosystem.</p>
<p>From my perspective, though time will tell, this update has the potential to be a real game changer. It brings what users expect: a familiar, secure, and frictionless authentication flow.</p>
<p>It might sound a bit ironic at first - we're integrating Google, after all - but I'm genuinely happy to ship this feature without compromising on the core values: providing developers secure features and modern tools with a state-of-the-art developer experience, while empowering them with full control over a cloud-native serverless infrastructure.</p>
<p>Let's see how it all comes together.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-why-it-matters">💡 Why It Matters<a href="https://juno.build/blog/google-sign-in-comes-to-juno#-why-it-matters" class="hash-link" aria-label="Direct link to 💡 Why It Matters" title="Direct link to 💡 Why It Matters" translate="no">​</a></h2>
<p>Authentication is one of those things every product needs but, it's complex, it touches security, and it's easy to get wrong.</p>
<p>Until now on Juno, developers could use Internet Identity, which has its strengths but also its weaknesses. It provides an unfamiliar login flow - is it an authentication provider or a password manager? - and it's not a well-known product outside of its niche.</p>
<p>Passkeys were also added recently, but you only have to scroll through tech Twitter to see that for every person who loves them, there's another who absolutely hates them.</p>
<p>That's why bringing native Google Sign-In to Juno matters. Developers can now offer their users a familiar, frictionless login flow - and let's be honest, most people are used to this signing and don't care much about doing it differently.</p>
<p>At the same time, this doesn't mean giving up control. The authentication process happens entirely within your Satellite, using the OpenID Connect standard.</p>
<p>You can obviously combine multiple sign-in methods in one project, offering your users the choice that best fits their needs.</p>
<p>When it comes to Juno itself, this also matters for two reasons: it potentially makes onboarding - through the Console - more accessible for web developers who don't care about decentralization but do care about owning their infrastructure ("self-hosting"). And it opens the door to future integrations with other providers. I still hope one day to have a better GitHub integration, and this might be a step toward it.</p>
<p>Long story short, it might look like a trivial change - just a couple of functions and a bit of configuration - but it's another step toward Juno's long-term goal of making it possible to build and scale modern cloud products without compromising on what matters most: empowering developers and their users.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-how-it-works">⚙️ How It Works<a href="https://juno.build/blog/google-sign-in-comes-to-juno#%EF%B8%8F-how-it-works" class="hash-link" aria-label="Direct link to ⚙️ How It Works" title="Direct link to ⚙️ How It Works" translate="no">​</a></h2>
<p>When a user signs in with Google, Juno follows the OpenID Connect (OIDC) standard to keep everything secure and verifiable.</p>
<ol>
<li class="">The user signs in with Google.</li>
<li class="">Google verifies their credentials and issues a signed OpenID Connect token.</li>
<li class="">After redirecting to your app, that signed token (JWT) is sent to your Satellite.</li>
<li class="">Inside the container, the token and its signature are verified, and the user's information (such as email or profile) is extracted.</li>
<li class="">The Satellite then creates a secure session for the user.</li>
<li class="">Once authenticated, the user can start interacting with your app built on top of your container's features.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-infrastructure">🧩 Infrastructure<a href="https://juno.build/blog/google-sign-in-comes-to-juno#-infrastructure" class="hash-link" aria-label="Direct link to 🧩 Infrastructure" title="Direct link to 🧩 Infrastructure" translate="no">​</a></h2>
<p>At this point, you get the idea: aside from using Google as a third-party provider, there's no hidden “big tech” backend behind this. Everything else happens within your Satellite.</p>
<p>The credentials you configure - your Google project and OAuth 2.0 Client ID - are yours. In comparison, those used in Internet Identity are owned by the DFINITY Foundation. So, this approach might feel less empowering for end users or more empowering for developers. You can see the glass half full or half empty here.</p>
<p>To validate tokens on the backend, your container needs access to the public keys Google uses to sign them. Since those keys rotate frequently, fetching them directly would introduce extra cost and resource overhead.</p>
<p>That's why the Observatory - a shared module owned by Juno (well, by me) - comes in. It caches and provides Google's public keys, keeping verification fast, efficient, and cost-effective.</p>
<p>Because Juno is modular, developers who want full control or higher redundancy can run their own Observatory instance. Reach out if you're interested.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-setup-overview">🪄 Setup Overview<a href="https://juno.build/blog/google-sign-in-comes-to-juno#-setup-overview" class="hash-link" aria-label="Direct link to 🪄 Setup Overview" title="Direct link to 🪄 Setup Overview" translate="no">​</a></h2>
<p>Getting started only takes a short configuration. Once your Google project is set up, add your Client ID to your <code>juno.config</code> file:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineConfig </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/config"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">default</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineConfig</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  satellite</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    ids</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      development</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"&lt;DEV_SATELLITE_ID&gt;"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      production</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"&lt;PROD_SATELLITE_ID&gt;"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    source</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"dist"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    authentication</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      google</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        clientId</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"1234567890-abcde12345fghijklmno.apps.googleusercontent.com"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Then apply it using the CLI or manually through the Console UI. That's it, it's configured.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-usage">🧑‍💻 Usage<a href="https://juno.build/blog/google-sign-in-comes-to-juno#-usage" class="hash-link" aria-label="Direct link to 🧑‍💻 Usage" title="Direct link to 🧑‍💻 Usage" translate="no">​</a></h2>
<p>To add the sign-in to your app, it only takes a single function call - typically tied to a button like "Continue with Google".</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signIn </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> google</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>For now, it uses the standard redirect flow, meaning users are sent to Google and then redirected back to your app.</p>
<p>You'll just need to handle that callback on the redirect route with:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> handleRedirectCallback </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">handleRedirectCallback</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>I'll soon unleash support for FedCM (Federated Credential Management) as well.</p>
<p>Aside from that, nothing new - the rest works exactly the same.</p>
<p>Regardless of which authentication provider you're using, you can still track a user's authentication state through a simple callback:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> onAuthStateChange </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:#ff5df9">onAuthStateChange</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token operator" style="color:white">:</span><span class="token plain"> User </span><span class="token operator" style="color:white">|</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">null</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"User:"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>And because type safety is the way, you can now safely access provider-specific data without writing endless if statements:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> isWebAuthnUser</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> isGoogleUser </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token function" style="color:#ff5df9">isWebAuthnUser</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">providerData</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">aaguid</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"> </span><span class="token comment" style="color:#707070;font-style:italic">// Safely typed ✅</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token function" style="color:#ff5df9">isGoogleUser</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">providerData</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">email</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"> </span><span class="token comment" style="color:#707070;font-style:italic">// Safely typed ✅</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-managing-users">🛠️ Managing Users<a href="https://juno.build/blog/google-sign-in-comes-to-juno#%EF%B8%8F-managing-users" class="hash-link" aria-label="Direct link to 🛠️ Managing Users" title="Direct link to 🛠️ Managing Users" translate="no">​</a></h2>
<p>Once users start signing in, you can view and manage them directly in the <strong>Authentication</strong> section of the <a href="https://console.juno.build/" target="_blank" rel="noopener noreferrer">Console<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>.</p>
<p>Each user entry displays key details such as:</p>
<ul>
<li class="">Name and email address</li>
<li class="">Authentication provider</li>
<li class="">Profile picture (if available)</li>
</ul>
<p>This view also lets you filter, sort, refresh or ban users etc.</p>
<p><img decoding="async" loading="lazy" alt="Screenshot of the Juno Console showing users authenticated with Google" src="https://juno.build/assets/images/auth-view-with-signed-in-users-95fa531d91eb445d34801f4233b4922a.webp" width="1200" height="837" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-learn-more">📚 Learn More<a href="https://juno.build/blog/google-sign-in-comes-to-juno#-learn-more" class="hash-link" aria-label="Direct link to 📚 Learn More" title="Direct link to 📚 Learn More" translate="no">​</a></h2>
<p>You can find all the details - including setup, configuration, and advanced options - in the documentation:</p>
<ul>
<li class=""><a href="https://juno.build/docs/build/authentication/google">Google Authentication</a></li>
<li class=""><a href="https://juno.build/docs/build/authentication">Authentication Overview</a></li>
</ul>
<p>If you haven't tried Juno yet, head over to <a href="https://console.juno.build/" target="_blank" rel="noopener noreferrer">console.juno.build<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> and sign in with Google to get started.</p>
<p>Ultimately, I can tell you stories, but nothing beats trying it yourself.</p>
<p>To infinity and beyond,
<br>David</p>
<hr>
<p>Reach out on <a href="https://discord.gg/wHZ57Z2RAG" target="_blank" rel="noopener noreferrer">Discord<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> or <a href="https://oc.app/community/vxgpi-nqaaa-aaaar-ar4lq-cai/?ref=xanzv-uaaaa-aaaaf-aneba-cai" target="_blank" rel="noopener noreferrer">OpenChat<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> for any questions.</p>
<p>Stay connected with Juno on <a href="https://twitter.com/junobuild" target="_blank" rel="noopener noreferrer">X/Twitter<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>.</p>
<p>⭐️⭐️⭐️ stars are also much appreciated: visit the <a href="https://github.com/junobuild/juno" target="_blank" rel="noopener noreferrer">GitHub repo<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> and show your support!</p>]]></content:encoded>
            <category>passkeys</category>
            <category>passwordless</category>
            <category>authentication</category>
            <category>webauthn</category>
            <category>sign-in</category>
            <category>sign-up</category>
            <category>javascript</category>
            <category>sdk</category>
        </item>
        <item>
            <title><![CDATA[New (kind of) breadcrumbs nav, who dis?]]></title>
            <link>https://juno.build/blog/2025-10-09-new-kind-of-breadcrumbs-nav-who-dis</link>
            <guid>https://juno.build/blog/2025-10-09-new-kind-of-breadcrumbs-nav-who-dis</guid>
            <pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A screenshot of the new Console UI with navigation on the Datastore page]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://github.com/user-attachments/assets/ee45b372-4958-4634-8e12-3178399b7d4d" alt="A screenshot of the new Console UI with navigation on the Datastore page" class="img_ev3q"></p>
<p>I <a href="https://github.com/junobuild/juno/releases/tag/v0.0.58" target="_blank" rel="noopener noreferrer">tagged<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> a new release as I deployed a new version of the <a href="https://console.juno.build/" target="_blank" rel="noopener noreferrer">Console UI<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> to mainnet.</p>
<p>Aside from the updated navigation, which now displays the page title within breadcrumb-style navigation, and a few minor fixes, not much has changed feature-wise.</p>
<p>The biggest change in the frontend's codebase, which explains why so many files were touched, is a refactor to adopt the new pattern I’ve been using for DID declarations.</p>
<p>Instead of relying on auto-imported separate types, I now prefer grouping factories in a single module, exporting them from there, and importing the types through a suffixed module DID alias.</p>
<p>You can check out the pattern in Juno's <a href="https://github.com/junobuild/juno/tree/main/src/frontend" target="_blank" rel="noopener noreferrer">frontend<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> codebase or in the <a href="https://github.com/junobuild/juno-js/tree/main/packages/ic-client" target="_blank" rel="noopener noreferrer">ic-client<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> JS library. If you're curious about it, let me know.</p>
<p>It’s a small structural shift that makes the code much cleaner and more readable.</p>
<p>Finally, there are a few new E2E tests added in this repo and in the CLI.</p>
<p>To infinity and beyond 🍞✨<br>David</p>]]></content:encoded>
            <category>release</category>
            <category>ui</category>
            <category>console</category>
            <category>frontend</category>
        </item>
        <item>
            <title><![CDATA[Offline Snapshots with the CLI]]></title>
            <link>https://juno.build/blog/offline-snapshots-with-the-cli</link>
            <guid>https://juno.build/blog/offline-snapshots-with-the-cli</guid>
            <pubDate>Mon, 06 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>Here is a small but handy update for your toolbox: you can now <strong>download and upload snapshots offline</strong> with the Juno CLI. 🧰</p>
<p>That means you can:</p>
<ul>
<li class="">Keep a local copy of your module’s state</li>
<li class="">Stash it somewhere safe, just in case <!-- -->😅</li>
<li class="">Restore it when needed</li>
<li class="">Or even move it between Satellites</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">juno snapshot download </span><span class="token parameter variable" style="color:white">--target</span><span class="token plain"> satellite</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">juno snapshot upload </span><span class="token parameter variable" style="color:white">--target</span><span class="token plain"> satellite </span><span class="token parameter variable" style="color:white">--dir</span><span class="token plain"> .snapshots/0x00000060101</span><br></div></code></pre></div></div>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">👋 No Juno livestream today, but here's a little gift for your toolbox.<br><br>You can now download and upload snapshots OFFLINE with the CLI. 🧰💾 <a href="https://t.co/IW5jHyEBTD">pic.twitter.com/IW5jHyEBTD</a></p>— Juno (@junobuild) <a href="https://twitter.com/junobuild/status/1975184397402812752?ref_src=twsrc%5Etfw">October 6, 2025</a></blockquote>
<!-- -->]]></content:encoded>
            <category>release</category>
            <category>cli</category>
            <category>scripts</category>
            <category>snapshot</category>
            <category>offline</category>
        </item>
        <item>
            <title><![CDATA[Build & Run Scripts with “juno run”]]></title>
            <link>https://juno.build/blog/juno-run-scripts</link>
            <guid>https://juno.build/blog/juno-run-scripts</guid>
            <pubDate>Fri, 26 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Say hello to juno run 👋]]></description>
            <content:encoded><![CDATA[<p>Say hello to <code>juno run</code> 👋</p>
<p>Build custom scripts that already know your env, profile &amp; config.<br>
<!-- -->Write them in JS/TS.<br>
<!-- -->Run with the CLI. ⚡️</p>
<p>🍒 on top? Works out of the box in GitHub Actions!</p>
<p>For example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineRun </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/config"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> onRun </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineRun</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> mode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> profile </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">run</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> satelliteId</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> identity </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"Running task with:"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      mode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      profile</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      satelliteId</span><span class="token operator" style="color:white">:</span><span class="token plain"> satelliteId</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">toText</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      whoami</span><span class="token operator" style="color:white">:</span><span class="token plain"> identity</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">getPrincipal</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">toText</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Run it with:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">juno run </span><span class="token parameter variable" style="color:white">--src</span><span class="token plain"> ./my-task.ts</span><br></div></code></pre></div></div>
<p>Now, let’s suppose you want to fetch a document from your Satellite’s Datastore (“from your canister’s little DB”) and export it to a file:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> getDoc </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineRun </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/config"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> jsonReplacer </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@dfinity/utils"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> writeFile </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"node:fs/promises"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> onRun </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineRun</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> mode </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">run</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">context</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> key </span><span class="token operator" style="color:white">=</span><span class="token plain"> mode </span><span class="token operator" style="color:white">===</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"staging"</span><span class="token plain"> </span><span class="token operator" style="color:white">?</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"123"</span><span class="token plain"> </span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"456"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> doc </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">getDoc</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      collection</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"demo"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      key</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      satellite</span><span class="token operator" style="color:white">:</span><span class="token plain"> context</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">writeFile</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"./mydoc.json"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token constant" style="color:white">JSON</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">stringify</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">doc</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> jsonReplacer</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token number" style="color:white">2</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Fancy ✨</p>
<p>And since it’s TS/JS, you can obviously use any libraries to perform admin tasks as well.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> defineRun </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/config"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> IcrcLedgerCanister </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@dfinity/ledger-icrc"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> createAgent </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@dfinity/utils"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> onRun </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineRun</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> mode </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function-variable function" style="color:#ff5df9">run</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> identity</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> container</span><span class="token operator" style="color:white">:</span><span class="token plain"> host </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">mode </span><span class="token operator" style="color:white">!==</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"development"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token keyword" style="color:#b0baff">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">new</span><span class="token plain"> </span><span class="token class-name" style="color:#b0baff">Error</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"Only for fun!"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> agent </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">createAgent</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      identity</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      host</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> metadata </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token operator" style="color:white">=</span><span class="token plain"> IcrcLedgerCanister</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">create</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      agent</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      canisterId</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token constant" style="color:white">MY_LEDGER_CANISTER_ID</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> data </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">metadata</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Coolio?</p>
<p>I’ll demo it next Monday in Juno Live.
🎥 <a href="https://youtube.com/@junobuild" target="_blank" rel="noopener noreferrer">https://youtube.com/@junobuild<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>
<p>Happy week-end ☀️</p>]]></content:encoded>
            <category>release</category>
            <category>cli</category>
            <category>scripts</category>
        </item>
        <item>
            <title><![CDATA[Host Frontends on Stable Memory]]></title>
            <link>https://juno.build/blog/host-frontends-on-stable-memory</link>
            <guid>https://juno.build/blog/host-frontends-on-stable-memory</guid>
            <pubDate>Mon, 22 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>A new release is out — <code>v0.0.57</code> 🚀</p>
<p>✨ Host your frontend on heap or stable memory<br>
<!-- -->🔑 Internet Identity login with <a href="https://id.ai/" target="_blank" rel="noopener noreferrer">https://id.ai<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><br>
<!-- -->🦖 Fixes &amp; improvements</p>
<p>Release notes 👉 <a href="https://github.com/junobuild/juno/releases/tag/v0.0.57" target="_blank" rel="noopener noreferrer">Release v0.0.57 · junobuild/juno<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/2/1/21910345ec0b3d56bd78d9f55a32860a20997f00_2_1380x956.jpeg" alt="Console hosting &amp; identity update" class="img_ev3q"></p>]]></content:encoded>
            <category>release</category>
            <category>hosting</category>
            <category>identity</category>
        </item>
        <item>
            <title><![CDATA[Labels & Quick Access in Console]]></title>
            <link>https://juno.build/blog/labels-quick-access</link>
            <guid>https://juno.build/blog/labels-quick-access</guid>
            <pubDate>Thu, 11 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>A new release is out — <code>v0.0.56</code> 🚀</p>
<p>This release focuses on frontend changes in the Console:</p>
<ul>
<li class="">You can now label your Satellites with environment flags and tags. These appear in the launchpad, switcher, and overview. On the launchpad, they can also be used as search filters to quickly find the right Satellite.</li>
<li class="">A new navigation feature – called “Spotlight” or “Quick Access” – lets you jump anywhere in the Console or run actions (such as changing the theme) in seconds. Open it with the search icon in the navbar or by pressing <strong>Ctrl/Cmd + K</strong>.</li>
</ul>
<p>Hopefully these make building with the Console a little more fun (and faster)!</p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/8/2/828f1e207215504ed701ee47bf085d3cbf6e9bb8_2_1366x1000.jpeg" alt="Console label &amp; quick access UI" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/c/f/cffb2d23103fcaefedfb25587bda8fb94351182d_2_1366x1000.jpeg" alt="Spotlight / Quick Access UI" class="img_ev3q"></p>]]></content:encoded>
            <category>release</category>
            <category>console</category>
            <category>frontend</category>
        </item>
        <item>
            <title><![CDATA[Passkeys Authentication Is Here]]></title>
            <link>https://juno.build/blog/passkeys-authentication-is-here</link>
            <guid>https://juno.build/blog/passkeys-authentication-is-here</guid>
            <pubDate>Thu, 04 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[We're adding Passkeys as a built-in authentication method. With passwordless authentication powered by WebAuthn, users can sign up and sign in using device-native authenticators like Face ID, Touch ID, or their browser's password manager. The JavaScript SDK has also been updated with changes to sign-in and sign-out flows, making authentication simpler and more predictable for developers.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/passkeys-authentication-is-here-43c5075d7199d322001387e171adbe87.webp" width="1200" height="630" class="img_ev3q"></p>
<hr>
<p>Authentication is a core part of building any app. Until now, developers on Juno have relied on third-party providers like Internet Identity and NFID. Today we're providing a new option: <strong>Passkeys</strong>.</p>
<p>This new authentication option is available to all developers using the latest Juno SDK and requires the most recent version of your Satellite containers. You can now enable Passkeys alongside existing providers, and the JavaScript SDK has been updated to make authentication APIs more consistent across sign-in, sign-out, and session management.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-what-are-passkeys">🔑 What Are Passkeys?<a href="https://juno.build/blog/passkeys-authentication-is-here#-what-are-passkeys" class="hash-link" aria-label="Direct link to 🔑 What Are Passkeys?" title="Direct link to 🔑 What Are Passkeys?" translate="no">​</a></h2>
<p>Passkeys are a passwordless authentication method built into modern devices and browsers. They let users sign up and sign in using secure digital keys stored in iCloud Keychain, Google Password Manager, or directly in the browser with Face ID, Touch ID, or a simple device unlock instead of a password.</p>
<p>Under the hood, Passkeys rely on the <a href="https://www.w3.org/TR/webauthn-2/" target="_blank" rel="noopener noreferrer">WebAuthn standard<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> and the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API" target="_blank" rel="noopener noreferrer">web API<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> that enables browsers and devices to create and use cryptographic credentials. Passkeys are essentially a user-friendly layer on top of WebAuthn.</p>
<p>When stored in a password manager like iCloud Keychain or Google Password Manager, passkeys sync across a user’s devices, making them more resilient, though this does require trusting the companies that provide those services. If stored only in the browser, however, they can be lost if the browser is reset or uninstalled.</p>
<p>The good news is that most modern platforms already encourage syncing passkeys across devices, which makes them convenient for everyday use, giving users a smooth and safe way to log into applications.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-choosing-between-providers">🤔 Choosing Between Providers<a href="https://juno.build/blog/passkeys-authentication-is-here#-choosing-between-providers" class="hash-link" aria-label="Direct link to 🤔 Choosing Between Providers" title="Direct link to 🤔 Choosing Between Providers" translate="no">​</a></h2>
<p>Each authentication method has its strengths and weaknesses. Passkeys provide a familiar, device-native login experience with Face ID, Touch ID, or device unlock, relying on either the browser or a password manager for persistence. Internet Identity and NFID, on the other hand, offer privacy-preserving flows aligned with the Internet Computer, but they are less familiar to mainstream users and involve switching context into a separate window.</p>
<p><img decoding="async" loading="lazy" alt="When in doubt... why not both?" src="https://juno.build/assets/images/why-not-both-3c15b38bd6b81a508327e5dd8a5dbe20.webp" width="328" height="328" class="img_ev3q"></p>
<p>In practice, many developers will probably combine Passkeys and Internet Identity side by side, as we do in the starter templates we provide.</p>
<p>Ultimately, the right choice depends on your audience and product goals, balancing usability, privacy, and ecosystem integration.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-how-to-use-passkeys">🚀 How to Use Passkeys<a href="https://juno.build/blog/passkeys-authentication-is-here#-how-to-use-passkeys" class="hash-link" aria-label="Direct link to 🚀 How to Use Passkeys" title="Direct link to 🚀 How to Use Passkeys" translate="no">​</a></h2>
<p>Using the new Passkeys in your app should be straightforward with the latest JavaScript SDK.</p>
<p>To register a new user with a passkey, you call <code>signUp</code> with the <code>webauthn</code> option:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signUp </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signUp</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  webauthn</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>For returning users, <code>signIn</code> works the same way, using the passkey they already created:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signIn </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  webauthn</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>As you can notice, unlike with existing third-party providers, using Passkeys requires a distinct sign-up and sign-in flow. This is because the WebAuthn standard is designed so that an app cannot know in advance whether the user has an existing passkey, and this is intentional for privacy reasons. Users must therefore explicitly follow either the sign-up or sign-in path.</p>
<p>It is also worth noting that during sign-up, the user will be asked to use their authenticator twice:</p>
<ul>
<li class="">once to create the passkey on their device</li>
<li class="">and once again to sign the session that can be used to interact with your Satellite.</li>
</ul>
<p>Given these multiple steps, we added an onProgress callback to the various flows. This allows you to hook into the progression and update your UI, for example to show a loading state or step indicators while the user completes the flow.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signUp </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signUp</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  webauthn</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    options</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token function-variable function" style="color:#ff5df9">onProgress</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> step</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> state </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token comment" style="color:#707070;font-style:italic">// You could update your UI here</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"Progress:"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> step</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> state</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-updates-to-the-sdk">🛠️ Updates to the SDK<a href="https://juno.build/blog/passkeys-authentication-is-here#%EF%B8%8F-updates-to-the-sdk" class="hash-link" aria-label="Direct link to 🛠️ Updates to the SDK" title="Direct link to 🛠️ Updates to the SDK" translate="no">​</a></h2>
<p>Alongside introducing Passkeys, we also took the opportunity to clean up and simplify the authentication APIs in the JavaScript SDK.</p>
<hr>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="mandatory-provider-in-signin">Mandatory provider in signIn<a href="https://juno.build/blog/passkeys-authentication-is-here#mandatory-provider-in-signin" class="hash-link" aria-label="Direct link to Mandatory provider in signIn" title="Direct link to Mandatory provider in signIn" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-important admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>important</div><div class="admonitionContent_BuS1"><p>This is a breaking change.</p></div></div>
<p>Previously, calling <code>signIn()</code> without arguments defaulted to Internet Identity. With the introduction of Passkeys, we decided to drop the default. From now on, you must explicitly specify which provider to use for each sign-in call. This makes the API more predictable and avoids hidden assumptions.</p>
<p>In earlier versions, providers could also be passed as class objects. To prevent inconsistencies and align with the variant pattern used across our tooling, providers (and their options) must now be passed through an object.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signIn </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:#707070;font-style:italic">// Internet Identity</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> internet_identity</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:#707070;font-style:italic">// NFID</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> nfid</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:#707070;font-style:italic">// Passkeys</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> webauthn</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="page-reload-on-signout">Page reload on signOut<a href="https://juno.build/blog/passkeys-authentication-is-here#page-reload-on-signout" class="hash-link" aria-label="Direct link to Page reload on signOut" title="Direct link to Page reload on signOut" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-important admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>important</div><div class="admonitionContent_BuS1"><p>This is a breaking change.</p></div></div>
<p>By default, calling <code>signOut</code> will automatically reload the page (<code>window.location.reload</code>) after a successful logout. This is a common pattern in sign-out flows that ensures the application restarts from a clean state.</p>
<p>If you wish to opt out, the library still clears its internal state and authentication before the reload, and you can use the <code>windowReload</code> option set to <code>false</code>:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> signOut </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">await</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">signOut</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> windowReload</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token boolean" style="color:white">false</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="authsubscribe-renamed-to-onauthstatechange">authSubscribe renamed to onAuthStateChange<a href="https://juno.build/blog/passkeys-authentication-is-here#authsubscribe-renamed-to-onauthstatechange" class="hash-link" aria-label="Direct link to authSubscribe renamed to onAuthStateChange" title="Direct link to authSubscribe renamed to onAuthStateChange" translate="no">​</a></h3>
<p>To make the API more consistent with the industry standards, we introduced a new method called <code>onAuthStateChange</code>. It replaces <code>authSubscribe</code>, which is now marked as deprecated but will continue to work for the time being.</p>
<p>The behavior remains the same: you can reactively track when a user signs in or out, and unsubscribe when you no longer need updates.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> onAuthStateChange </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/core"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:#b0baff">const</span><span class="token plain"> unsubscribe </span><span class="token operator" style="color:white">=</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">onAuthStateChange</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:white">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token builtin" style="color:#ff5df9">console</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:#ff5df9">log</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:#b0baff">"User:"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:#707070;font-style:italic">// Later, stop listening</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:#ff5df9">unsubscribe</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-learn-more">📚 Learn More<a href="https://juno.build/blog/passkeys-authentication-is-here#-learn-more" class="hash-link" aria-label="Direct link to 📚 Learn More" title="Direct link to 📚 Learn More" translate="no">​</a></h2>
<p>Passkeys are now available, alongside updates to the authentication JS APIs. With passwordless sign-up and sign-in built into modern devices, your users get a smoother experience.</p>
<p>Check out the updated documentation for details on:</p>
<ul>
<li class=""><a href="https://juno.build/docs/build/authentication/passkeys#sign-up">signUp</a></li>
<li class=""><a href="https://juno.build/docs/build/authentication/passkeys#sign-in">signIn</a></li>
<li class=""><a href="https://juno.build/docs/build/authentication/utilities#sign-out">signOut</a></li>
<li class=""><a href="https://juno.build/docs/build/authentication/utilities#listening-to-auth-changes">onAuthStateChange</a></li>
</ul>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-whats-next">👀 What's Next<a href="https://juno.build/blog/passkeys-authentication-is-here#-whats-next" class="hash-link" aria-label="Direct link to 👀 What's Next" title="Direct link to 👀 What's Next" translate="no">​</a></h2>
<p>Passkeys are available today for developers building with Satellite containers and the JavaScript SDK.</p>
<p>Next, we'll bring Passkey support directly into the Console UI, so new developers can register easily and you can too.</p>
<p>To infinity and beyond,<br>
<!-- -->David</p>
<hr>
<p>Stay connected with Juno by following us on <a href="https://twitter.com/junobuild" target="_blank" rel="noopener noreferrer">X/Twitter<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>.</p>
<p>Reach out on <a href="https://discord.gg/wHZ57Z2RAG" target="_blank" rel="noopener noreferrer">Discord<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> or <a href="https://oc.app/community/vxgpi-nqaaa-aaaar-ar4lq-cai/?ref=xanzv-uaaaa-aaaaf-aneba-cai" target="_blank" rel="noopener noreferrer">OpenChat<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> for any questions.</p>
<p>⭐️⭐️⭐️ stars are also much appreciated: visit the <a href="https://github.com/junobuild/juno" target="_blank" rel="noopener noreferrer">GitHub repo<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> and show your support!</p>]]></content:encoded>
            <category>passkeys</category>
            <category>passwordless</category>
            <category>authentication</category>
            <category>webauthn</category>
            <category>sign-in</category>
            <category>sign-up</category>
            <category>javascript</category>
            <category>sdk</category>
        </item>
        <item>
            <title><![CDATA[Faster Deploys & Precompression]]></title>
            <link>https://juno.build/blog/faster-deploys-precompression</link>
            <guid>https://juno.build/blog/faster-deploys-precompression</guid>
            <pubDate>Thu, 14 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>A new release is out — <code>v0.0.54</code> 🚀</p>
<p>Here are a few highlights:</p>
<p>⚡️ Faster deploys with proposals batching<br>
<!-- -->📦 Smarter precompression (optional Brotli + replace mode)<br>
<!-- -->🔀 Redirects fixed<br>
<!-- -->✨ Shinier experience when deploying in your terminal</p>
<p>Checkout the release notes for details 👉 <a href="https://github.com/junobuild/juno/releases/tag/v0.0.54" target="_blank" rel="noopener noreferrer">Release v0.0.54 · junobuild/juno<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>
<p>Example of the new configuration option <code>precompress</code>:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword" style="color:#b0baff">default</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineConfig</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  satellite</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    ids</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      production</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"qsgjb-riaaa-aaaaa-aaaga-cai"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    source</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"dist"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    precompress</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      algorithm</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"brotli"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      pattern</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"**/*.+(css|js|mjs|html)"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      mode</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"replace"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>]]></content:encoded>
            <category>release</category>
            <category>deploy</category>
            <category>performance</category>
        </item>
        <item>
            <title><![CDATA[Freezing, Gzip, & Console Enhancements]]></title>
            <link>https://juno.build/blog/freezing-gzip-console-updates</link>
            <guid>https://juno.build/blog/freezing-gzip-console-updates</guid>
            <pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>A new release is out — <code>v0.0.52</code> 🚀</p>
<p>Here are a few highlights:<br>
<!-- -->🧊 Longer default freezing thresholds<br>
<!-- -->✅ Gzipped HTML<br>
<!-- -->🔐 Allowed Callers<br>
<!-- -->🛠 CLI Improvements<br>
<!-- -->🖥 Polished Console UI</p>
<p>Checkout the release notes for details 👉 <a href="https://github.com/junobuild/juno/releases/tag/v0.0.52" target="_blank" rel="noopener noreferrer">Release v0.0.52 · junobuild/juno<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>
<p>Let me know if anything looks fishy — and happy coding! 👨‍🔧</p>
<hr>
<p>🖥️ Two screenshots from the Console new features</p>
<p>The new “Notifications” component:</p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/0/b/0be9fd82d2855679e2e636b9625e8809c86d36f9_2_1304x1000.jpeg" alt="Notifications UI" class="img_ev3q"></p>
<p>The overall look: collapsible menu, redesigned tabs, more prominent actions, and more.</p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/3/e/3e14cf7042d73a47ada14288960028e85bdb1955_2_1304x1000.jpeg" alt="Console UI Update" class="img_ev3q"></p>
<hr>
<p>As a side note on this release: aside from the custom domain feature, I think it’s now possible to configure your entire project — including authentication, data, storage, and emulator — directly within the Juno config file. Plus with type safety as the cherry on top.</p>
<p>This is especially handy for maintainability or if your project can be forked.</p>
<p>Here’s an example config that shows where and how the project is deployed, which headers to apply to assets, defines the structure of that data, and which image to use when running the emulator with Podman:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword module" style="color:#b0baff">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token imports"> defineConfig </span><span class="token imports punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#b0baff">from</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"@junobuild/config"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token doc-comment comment" style="color:#707070;font-style:italic">/** </span><span class="token doc-comment comment keyword" style="color:#b0baff;font-style:italic">@type</span><span class="token doc-comment comment" style="color:#707070;font-style:italic"> </span><span class="token doc-comment comment class-name punctuation" style="color:hsl(220, 14%, 71%);font-style:italic">{</span><span class="token doc-comment comment class-name keyword" style="color:#b0baff;font-style:italic">import</span><span class="token doc-comment comment class-name punctuation" style="color:hsl(220, 14%, 71%);font-style:italic">(</span><span class="token doc-comment comment class-name string" style="color:#b0baff;font-style:italic">'@junobuild/config'</span><span class="token doc-comment comment class-name punctuation" style="color:hsl(220, 14%, 71%);font-style:italic">)</span><span class="token doc-comment comment class-name punctuation" style="color:hsl(220, 14%, 71%);font-style:italic">.</span><span class="token doc-comment comment class-name" style="color:#b0baff;font-style:italic">JunoConfig</span><span class="token doc-comment comment class-name punctuation" style="color:hsl(220, 14%, 71%);font-style:italic">}</span><span class="token doc-comment comment" style="color:#707070;font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword module" style="color:#b0baff">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#b0baff">default</span><span class="token plain"> </span><span class="token function" style="color:#ff5df9">defineConfig</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:white">satellite</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">ids</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:white">development</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"jx5yt-yyaaa-aaaal-abzbq-cai"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:white">production</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"fmkjf-bqaaa-aaaal-acpza-cai"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">source</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"build"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">predeploy</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token string" style="color:#b0baff">"npm run build"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">storage</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:white">headers</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">source</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"**/*.png"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">headers</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token string" style="color:#b0baff">"Cache-Control"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"max-age=2592000"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">collections</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:white">datastore</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">collection</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"notes"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">read</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"managed"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">write</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"managed"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token literal-property property" style="color:white">memory</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"stable"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:white">emulator</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">runner</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:white">type</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"podman"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:white">satellite</span><span class="token operator" style="color:white">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>Documentation 👉 <a href="https://juno.build/docs/reference/configuration" target="_blank" rel="noopener noreferrer">https://juno.build/docs/reference/configuration<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></p>]]></content:encoded>
            <category>release</category>
            <category>console</category>
            <category>cli</category>
            <category>performance</category>
        </item>
        <item>
            <title><![CDATA[Build and Publish Serverless Functions with GitHub Actions]]></title>
            <link>https://juno.build/blog/serverless-functions-github-actions</link>
            <guid>https://juno.build/blog/serverless-functions-github-actions</guid>
            <pubDate>Thu, 19 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Serverless functions in TypeScript or Rust can now be built and published automatically using GitHub Actions. Full control. No compromises.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://juno.build/assets/images/serverless-functions-github-actions-b19d1f12963712cd2e85a9ef25355758.png" width="1200" height="914" class="img_ev3q"></p>
<hr>
<p>One of the principles that shaped Juno from day one was the idea of building apps with full ownership — no hidden infrastructure, no opaque servers.</p>
<p>No hypocrisy either.</p>
<p>If developers are encouraged to deploy code in containers they control, it feels inconsistent to rely on centralized infrastructure — like AWS or other Web2 cloud providers — to manage deployment pipelines or run the platform. With the exception of email notifications, Juno currently runs entirely on the Internet Computer — and that's a deliberate choice.</p>
<p>That doesn't mean being stubborn for the sake of it. It just means trying to push things forward without falling back on the old way unless absolutely necessary.</p>
<p>At the same time, developer experience matters — a lot. It shouldn't take a degree in DevOps to ship a backend function. Developers who would typically reach for a serverless option should be able to do so here too. And for those who prefer to stay local, it shouldn't feel like a downgrade — no one should be forced into CI automation if they don't want to.</p>
<p>That's why the new GitHub Actions for serverless functions are now generally available — for those who want automation, not obligation.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-automated-deployments-no-compromise">🚀 Automated Deployments, No Compromise<a href="https://juno.build/blog/serverless-functions-github-actions#-automated-deployments-no-compromise" class="hash-link" aria-label="Direct link to 🚀 Automated Deployments, No Compromise" title="Direct link to 🚀 Automated Deployments, No Compromise" translate="no">​</a></h2>
<p>With the latest release, it's now possible to:</p>
<ul>
<li class="">Build serverless functions written in TypeScript or Rust</li>
<li class="">Automatically publish them to a Satellite</li>
<li class="">Optionally propose or directly apply upgrades</li>
</ul>
<p>All within a GitHub Actions workflow. No manual builds, no extra setup — just code, commit, and push.</p>
<p>This makes it easier to fit Juno into an existing CI/CD pipeline or start a new one from scratch. The logic is bundled, metadata is embedded, and the container is ready to run.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-what-about-security">🔐 What About Security?<a href="https://juno.build/blog/serverless-functions-github-actions#-what-about-security" class="hash-link" aria-label="Direct link to 🔐 What About Security?" title="Direct link to 🔐 What About Security?" translate="no">​</a></h2>
<p>You might ask yourself: <em>"But what about the risk of giving CI full control over my infrastructure?"</em></p>
<p>That's where the improved access key (previously named <em>"Controllers"</em>) roles come in.</p>
<p>Instead of handing over the master key, you give CI just enough access to do its job — and nothing more.</p>
<p>Here's how the roles break down in plain terms:</p>
<ul>
<li class="">
<p><strong>Administrator</strong> – Full control. Can deploy, upgrade, stop, or delete any module. Powerful, but risky for automation. Might be useful if you're spinning up test environments frequently.</p>
</li>
<li class="">
<p><strong>Editor</strong> (Write) – Ideal for CI pipelines that deploy frontend assets or publish serverless functions. Can't upgrade those or stop and delete modules. A good default.</p>
</li>
<li class="">
<p><strong>Submitter</strong> 🆕 – The safest option. Can propose changes but not apply them. Someone still needs to review and approve in the Console or CLI. No surprises, no accidents.</p>
</li>
</ul>
<p>Use Editor for most CI tasks — it gives you automation without opening the blast radius.</p>
<p>Prefer an extra layer of review? Go with Submitter and keep a human in the loop.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-local-or-ci-your-choice">🧰 Local or CI: Your Choice<a href="https://juno.build/blog/serverless-functions-github-actions#-local-or-ci-your-choice" class="hash-link" aria-label="Direct link to 🧰 Local or CI: Your Choice" title="Direct link to 🧰 Local or CI: Your Choice" translate="no">​</a></h2>
<p>Nothing changes in the approach for developers who prefer local development. The CLI remains a first-class tool for building and deploying.</p>
<p>All the new capabilities — from publishing functions to proposing or applying upgrades — are available not just in GitHub Actions or the Console UI, but also fully supported in the CLI.</p>
<p>In fact, the CLI has been improved with a neat addition: you can now append <code>--mode development</code> to interact with the emulator. This allows you to fully mimic production behavior while developing locally. And of course, you can also use any mode to target any environment.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">juno functions upgrade </span><span class="token parameter variable" style="color:white">--mode</span><span class="token plain"> staging</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">juno deploy </span><span class="token parameter variable" style="color:white">--mode</span><span class="token plain"> development</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-satellites-cdn">🛰️ Satellite's CDN<a href="https://juno.build/blog/serverless-functions-github-actions#%EF%B8%8F-satellites-cdn" class="hash-link" aria-label="Direct link to 🛰️ Satellite's CDN" title="Direct link to 🛰️ Satellite's CDN" translate="no">​</a></h2>
<p>While building serverless functions was never an issue, enabling GitHub Actions to publish and deploy without giving away full control introduced a challenge. How do you let CI push code without handing it the keys to everything?</p>
<p>That's where the idea of a sort of CDN came in.</p>
<p>Each Satellite now has a reserved collection called <code>#_juno/releases</code>. It's like a staging area where CI can submit new WASM containers or frontend assets. If the access key has enough privileges, the submission is deployed right away. If not, it's stored as a pending change — waiting for someone to approve it manually via the Console or CLI.</p>
<p>This builds on the change-based workflow that was added to the Console last year. Funny enough, it brought the Console so close to being a Satellite itself that it became... basically a meta example of what you can build with Juno.</p>
<p>And here's the cherry on top: because there's now a CDN tracking versions, developers can rollback or switch between different function versions more easily. A new CDN tab in the Console UI (under Functions) gives you access to all past versions and history.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-frontend-deployments-too">🖼️ Frontend Deployments, Too<a href="https://juno.build/blog/serverless-functions-github-actions#%EF%B8%8F-frontend-deployments-too" class="hash-link" aria-label="Direct link to 🖼️ Frontend Deployments, Too" title="Direct link to 🖼️ Frontend Deployments, Too" translate="no">​</a></h2>
<p>Frontend deployment now benefits from the same change-based workflow. By default, when you run <code>juno deploy</code> or trigger a GitHub Action, the assets are submitted as pending changes — and applied automatically (if the access key allows it).</p>
<p>Want to skip that workflow? You still can. The immediate deployment path remains available — handy if something fails, or if you just prefer to keep things simple.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="️-github-actions-for-serverless-functions">🛠️ GitHub Actions for Serverless Functions<a href="https://juno.build/blog/serverless-functions-github-actions#%EF%B8%8F-github-actions-for-serverless-functions" class="hash-link" aria-label="Direct link to 🛠️ GitHub Actions for Serverless Functions" title="Direct link to 🛠️ GitHub Actions for Serverless Functions" translate="no">​</a></h2>
<p>Alright, enough chit-chat — here's how to publish your serverless functions on every push to main, straight from CI:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockTitle_OeMC">publish.yml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token key atrule" style="color:#b0baff">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> Publish Serverless Functions</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token key atrule" style="color:#b0baff">on</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token key atrule" style="color:#b0baff">workflow_dispatch</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token key atrule" style="color:#b0baff">push</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token key atrule" style="color:#b0baff">branches</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain">main</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token key atrule" style="color:#b0baff">jobs</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token key atrule" style="color:#b0baff">publish</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token key atrule" style="color:#b0baff">runs-on</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token key atrule" style="color:#b0baff">steps</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#b0baff">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> Check out the repo</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">uses</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> actions/checkout@v4</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#b0baff">uses</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> actions/setup</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain">node@v4</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">with</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token key atrule" style="color:#b0baff">node-version</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token number" style="color:white">24</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token key atrule" style="color:#b0baff">registry-url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token string" style="color:#b0baff">"https://registry.npmjs.org"</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#b0baff">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> Install Dependencies</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">run</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> npm ci</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#b0baff">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> Build</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">uses</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> junobuild/juno</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain">action@full</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">with</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token key atrule" style="color:#b0baff">args</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> functions build</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#b0baff">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> Publish</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">uses</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> junobuild/juno</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-</span><span class="token plain">action@full</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">with</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token key atrule" style="color:#b0baff">args</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> functions publish</span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token key atrule" style="color:#b0baff">env</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">          </span><span class="token key atrule" style="color:#b0baff">JUNO_TOKEN</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> secrets.JUNO_TOKEN </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-one-action-two-flavors">🌸 One Action, Two Flavors<a href="https://juno.build/blog/serverless-functions-github-actions#-one-action-two-flavors" class="hash-link" aria-label="Direct link to 🌸 One Action, Two Flavors" title="Direct link to 🌸 One Action, Two Flavors" translate="no">​</a></h2>
<p>Noticed the <code>@full</code> in the previous step?</p>
<p>That's because the GitHub Action now comes in two flavors:</p>
<ul>
<li class="">
<p><code>junobuild/juno-action</code> or <code>junobuild/juno-action@slim</code> – perfect for common use cases like deploying frontend assets or running simpler CLI tasks. No serverless build dependencies included, so it's faster and more "lightweight" (relatively, it still uses Docker underneath...).</p>
</li>
<li class="">
<p><code>junobuild/juno-action@full</code> – includes everything you need to build and publish serverless functions, with Rust and TypeScript support. It's heavier, but it does the job end to end.</p>
</li>
</ul>
<p>The right tool for the right job. Pick what fits.</p>
<hr>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="-where-this-is-going">🧭 Where This Is Going<a href="https://juno.build/blog/serverless-functions-github-actions#-where-this-is-going" class="hash-link" aria-label="Direct link to 🧭 Where This Is Going" title="Direct link to 🧭 Where This Is Going" translate="no">​</a></h2>
<p>This release isn't just about smoother deployments — it's a step toward making Juno feel like real infrastructure. Though, what is “real infrastructure” anyway? Whatever it is, this one doesn't come with the usual baggage.</p>
<p>Developers get to choose <strong>how</strong> they ship — locally or through CI. They get to decide <strong>what</strong> gets deployed and <strong>who</strong> can do it. They're not <strong>forced</strong> to rely on some big tech platform for their infra if they don't want to. And thanks to the new CDN and access control model, fast iteration and tight control can finally go hand in hand.</p>
<p>If you've been waiting for a way to ship backend logic without giving up on decentralization — or if you just like things working smoothly — this one's for you.</p>
<p>Go ahead.
Build it.
Push it.
Submit it.
Ship it.</p>
<p>To infinity and beyond,<br>
<!-- -->David</p>
<hr>
<p>Stay connected with Juno by following us on <a href="https://twitter.com/junobuild" target="_blank" rel="noopener noreferrer">X/Twitter<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a>.</p>
<p>Reach out on <a href="https://discord.gg/wHZ57Z2RAG" target="_blank" rel="noopener noreferrer">Discord<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> or <a href="https://oc.app/community/vxgpi-nqaaa-aaaar-ar4lq-cai/?ref=xanzv-uaaaa-aaaaf-aneba-cai" target="_blank" rel="noopener noreferrer">OpenChat<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> for any questions.</p>
<p>⭐️⭐️⭐️ stars are also much appreciated: visit the <a href="https://github.com/junobuild/juno" target="_blank" rel="noopener noreferrer">GitHub repo<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> and show your support!</p>]]></content:encoded>
            <category>serverless</category>
            <category>github-actions</category>
            <category>ci</category>
            <category>devtools</category>
            <category>typescript</category>
            <category>rust</category>
        </item>
        <item>
            <title><![CDATA[Analytics Campaign Tracking]]></title>
            <link>https://juno.build/blog/analytics-campaign-tracking</link>
            <guid>https://juno.build/blog/analytics-campaign-tracking</guid>
            <pubDate>Sun, 01 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi 👋]]></description>
            <content:encoded><![CDATA[<p>Hi 👋</p>
<p>A new release v0.0.50 is out! 🚀</p>
<p>This one brings two improvements to the Analytics:</p>
<p>📣 Campaign tracking is now supported! Just use standard UTM tags in your links — traffic sources like newsletters, ads, and social posts will show up directly in your dashboard. No extra setup needed.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:black;--prism-color:white"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:black;color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:#707070;font-style:italic"># For example</span><span class="token plain"></span><br></div><div class="token-line" style="color:white;text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">https://myapp.com/?utm_source</span><span class="token operator" style="color:white">=</span><span class="token plain">newsletter</span><span class="token operator" style="color:white">&amp;</span><span class="token assign-left variable" style="color:white">utm_medium</span><span class="token operator" style="color:white">=</span><span class="token plain">email</span><span class="token operator" style="color:white">&amp;</span><span class="token assign-left variable" style="color:white">utm_campaign</span><span class="token operator" style="color:white">=</span><span class="token plain">spring-launch</span><br></div></code></pre></div></div>
<p>🤖 Bot detection has also been improved by using HTTP headers directly from the container smart contract (instead of those passed in the requests). More accurate and secure that way.</p>
<p>Enjoy! 🧪📊</p>
<hr>
<ul>
<li class="">Docs 👉 <a href="https://juno.build/docs/build/analytics/" target="_blank" rel="noopener noreferrer">https://juno.build/docs/build/analytics/<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li>
<li class="">Release notes 👉 <a href="https://github.com/junobuild/juno/releases/tag/v0.0.50" target="_blank" rel="noopener noreferrer">https://github.com/junobuild/juno/releases/tag/v0.0.50<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li>
</ul>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/f/1/f1ba65f76421ede1f8daa4fc33634fd8739113c5_2_1226x1000.jpeg" alt="Analytics UTM tracking" class="img_ev3q"></p>]]></content:encoded>
            <category>release</category>
            <category>analytics</category>
            <category>tracking</category>
            <category>bots</category>
        </item>
        <item>
            <title><![CDATA[Monitoring Health Check]]></title>
            <link>https://juno.build/blog/monitoring-healthcheck</link>
            <guid>https://juno.build/blog/monitoring-healthcheck</guid>
            <pubDate>Fri, 09 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[I just shipped a release focuses solely on updates to the Console UI.]]></description>
            <content:encoded><![CDATA[<p>I just shipped a release focuses solely on updates to the <strong>Console UI</strong>.</p>
<p>The main change is the addition of a new <strong>Health Check</strong> section under “Monitoring”, along with a clearer breakdown of memory metrics.</p>
<p>I also revisited the notion of the “auto-refill threshold”, as the previous description was misleading or partial.</p>
<p>Lastly, the step related to the “authentication domain” in the hosting wizard has been simplified.</p>
<p>All these changes are, of course, documented.</p>
<ul>
<li class=""><a href="https://juno.build/docs/management/monitoring" target="_blank" rel="noopener noreferrer">Monitoring<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li>
<li class=""><a href="https://juno.build/docs/reference/settings#freezing-threshold" target="_blank" rel="noopener noreferrer">Freezing Threshold<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li>
<li class=""><a href="https://juno.build/docs/build/authentication/#domain-based-user-identity" target="_blank" rel="noopener noreferrer">Domain based User Identity<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li>
</ul>
<p>Happy weekend ☀️</p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/f/b/fb62f8ce5d8a357079411a108ce0c50472b852ce_2_1380x964.jpeg" alt="Health Check UI" class="img_ev3q"></p>]]></content:encoded>
            <category>release</category>
            <category>console</category>
            <category>monitoring</category>
        </item>
        <item>
            <title><![CDATA[Lighter Analytics Client]]></title>
            <link>https://juno.build/blog/lighter-analytics-client</link>
            <guid>https://juno.build/blog/lighter-analytics-client</guid>
            <pubDate>Mon, 05 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[This new release brings a major upgrade to Juno Analytics — now powered by native HTTP requests with no more web workers or IndexedDB.]]></description>
            <content:encoded><![CDATA[<p>This new release brings a major upgrade to <a href="https://juno.build/" target="_blank" rel="noopener noreferrer">Juno Analytics<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a> — now powered by native HTTP requests with no more web workers or IndexedDB.</p>
<p>The JS client is now over 90% (🔥) smaller (just 3KB gzipped!), and the dashboard supports paginated views, top time zones, and OS metrics.</p>
<p>There are a few breaking changes (‼️), so check the notes if you’re using analytics — and make sure to upgrade your Orbiter and JS libraries at the same time ⚠️.</p>
<p>Reach out if you have questions, happy to help!</p>
<p><img decoding="async" loading="lazy" src="https://us1.discourse-cdn.com/flex023/uploads/dfn/optimized/3X/4/1/41e31174e2c3a6bdc950fd95c95f4aca14c2b536_2_940x1000.jpeg" alt="New Juno Analytics Dashboard UI" class="img_ev3q"></p>]]></content:encoded>
            <category>release</category>
            <category>analytics</category>
            <category>dashboard</category>
            <category>performance</category>
        </item>
    </channel>
</rss>