<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Techtrails: Tech journal]]></title><description><![CDATA[Technical notes & tips gathered along the way]]></description><link>https://techtrails.io/s/tech-journal</link><image><url>https://substackcdn.com/image/fetch/$s_!mOPI!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90053d7-5b39-470b-9019-37ce873bc8d9_512x512.png</url><title>Techtrails: Tech journal</title><link>https://techtrails.io/s/tech-journal</link></image><generator>Substack</generator><lastBuildDate>Fri, 17 Apr 2026 10:30:09 GMT</lastBuildDate><atom:link href="https://techtrails.io/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Olivier Lance]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[techtrails@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[techtrails@substack.com]]></itunes:email><itunes:name><![CDATA[Olivier Lance]]></itunes:name></itunes:owner><itunes:author><![CDATA[Olivier Lance]]></itunes:author><googleplay:owner><![CDATA[techtrails@substack.com]]></googleplay:owner><googleplay:email><![CDATA[techtrails@substack.com]]></googleplay:email><googleplay:author><![CDATA[Olivier Lance]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Down the Kamal rabbit holes]]></title><description><![CDATA[Multi-arch builds, GitHub Container Registry, custom TLS certificate, conflicts with foreman, ...]]></description><link>https://techtrails.io/p/down-the-kamal-rabbit-holes</link><guid isPermaLink="false">https://techtrails.io/p/down-the-kamal-rabbit-holes</guid><dc:creator><![CDATA[Olivier Lance]]></dc:creator><pubDate>Thu, 19 Sep 2024 23:18:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!eXP4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eXP4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eXP4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 424w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 848w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 1272w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eXP4!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:809,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8544040,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eXP4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 424w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 848w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 1272w, https://substackcdn.com/image/fetch/$s_!eXP4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff19cd969-fcb7-45b1-aaa7-a7480b7ce56f_4608x2560.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="pullquote"><p>This is a post from my Tech Journal section, in which I explore technical topics and focus on how I overcome specific challenges.<br>If you're not into the tech stuff, you can unsubscribe from Tech Journal updates from <a href="https://techtrails.io/account">your account</a>.</p></div><p>OK, the title might be a bit &#8220;click-baity&#8221; &#128517;</p><p>The truth is, Kamal is super cool to setup!<br>I have never deployed an app from scratch so quickly.</p><p>I did end up spending time into 4 rabbit holes though, so I wanted to keep notes about what happened and how to overcome the issues I faced.</p><p>You know, just in case.</p><h1>Multi-arch build issues</h1><p>The first issue I encountered was somewhat of a tricky one, although the fix was simple in the end.</p><p>It's always like this, isn't it? &#128517;</p><p>After I setup Kamal for my project, I ran <code>kamal server bootstrap</code> followed by <code>kamal deploy</code>, as instructed.</p><p>Colorful logs started flowing on my screen and I sat back, amazed by the simplicity of it all.</p><p>The Docker build process started. Along came the bundling step, and gem names came trickling down the terminal.</p><p>And then, it hung. For a few minutes.<br>I thought it must be doing something big, and it was late, so I went to bed.</p><p>The next morning, it was still stuck on the same thing:</p><pre><code> DEBUG [0729c69a] &#9;#29 668.9 Bundled gems are installed into `/usr/local/bundle`
 DEBUG [0729c69a] &#9;#29 668.9 Post-install message from rubyzip:
 DEBUG [0729c69a] &#9;#29 668.9 RubyZip 3.0 is coming!
 DEBUG [0729c69a] &#9;#29 668.9 **********************
 DEBUG [0729c69a] &#9;#29 668.9 
 DEBUG [0729c69a] &#9;#29 668.9 The public API of some Rubyzip classes has been modernized to use named
 DEBUG [0729c69a] &#9;#29 668.9 parameters for optional arguments. Please check your usage of the
 DEBUG [0729c69a] &#9;#29 668.9 following classes:
 DEBUG [0729c69a] &#9;#29 668.9   * `Zip::File`
 DEBUG [0729c69a] &#9;#29 668.9   * `Zip::Entry`
 DEBUG [0729c69a] &#9;#29 668.9   * `Zip::InputStream`
 DEBUG [0729c69a] &#9;#29 668.9   * `Zip::OutputStream`
 DEBUG [0729c69a] &#9;#29 668.9 
 DEBUG [0729c69a] &#9;#29 668.9 Please ensure that your Gemfiles and .gemspecs are suitably restrictive
 DEBUG [0729c69a] &#9;#29 668.9 to avoid an unexpected breakage when 3.0 is released (e.g. ~&gt; 2.3.0).
 DEBUG [0729c69a] &#9;#29 668.9 See https://github.com/rubyzip/rubyzip for details. The Changelog also
 DEBUG [0729c69a] &#9;#29 668.9 lists other enhancements and bugfixes that have been implemented since
 DEBUG [0729c69a] &#9;#29 668.9 version 2.3.0.</code></pre><p>A second run led to the same issue.</p><p>So I started searching, and found a few threads about the problem. The one that led me to a solution is Discussion #747 on Kamal&#8217;s repository: <a href="https://github.com/basecamp/kamal/discussions/747">Deploy stucks on message about RubyZip 3.0 coming</a>.<br>Someone in there hints at the issue coming from Kamal building a cross-platform Docker image by default, targeted for both AMD64 (Intel/x86-64 compatible processors) and ARM64 (ARM architectures such as Ampere processors).<br>Apparently building for ARM64 from an Intel CPU tends to fail and hang, at least on a Mac.</p><p>Since I am building on an Intel Mac but also for an x86-64 server, I don't need to build for ARM. So I disabled the ARM build, and everything went smoothly after that!</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c1s9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c1s9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 424w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 848w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 1272w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c1s9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png" width="1442" height="342" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:342,&quot;width&quot;:1442,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:35953,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!c1s9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 424w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 848w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 1272w, https://substackcdn.com/image/fetch/$s_!c1s9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4dc6094-60a3-4659-92da-b82749a7af40_1442x342.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Everything?<br>Well, not exactly.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Is the suspense killing you? Subscribe for more tech adventures! &#128513;</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><h1>Using GHCR as Docker registry</h1><p>As hinted above, Kamal uses Docker to build an app &#8220;artifact&#8221; and deploy it onto your servers. In the process, it needs to push the locally built image to a container registry, from which it can pull it again for deployment from your servers.</p><p>Since I'm using GitHub to host my code, I wanted to keep things simple and use their Container Registry feature as well, instead of Docker Hub.</p><p>It's pretty straightforward to setup Kamal for this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Sbbc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Sbbc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 424w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 848w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 1272w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Sbbc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png" width="1442" height="442" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:442,&quot;width&quot;:1442,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71929,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Sbbc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 424w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 848w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 1272w, https://substackcdn.com/image/fetch/$s_!Sbbc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4d9e39-f22d-4f36-9c1a-caf52b61928f_1442x442.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The <code>KAMAL_REGISTRY_PASSWORD</code> comes from your <em>.env</em> file at the root of your project.<br>For things to work with GitHub Container Registry, you have to use <a href="https://github.com/settings/tokens/new">a new Classic Personal Access Token</a> (PAT) as your password.</p><p>I did this, but unfortunately it did not work immediately: as soon as Kamal tried to push the built image, it failed with an error:</p><pre><code>Error: unexpected status from POST request to https://ghcr.io/v2/techtrails/real-emails/blobs/uploads/: 403 Forbidden</code></pre><p>Kamal does manage to log into the registry as its first step, so the error was a bit unsettling: why could it log in, but not push an image to my repository registry?</p><p>Since I'm not pushing to my user GitHub (<a href="https://github.com/olance">https://github.com/olance</a>) but to my Techtrails organization (<a href="https://github.com/techtrails-io">https://github.com/techtrails-io</a>), I thought it might be an issue with my PAT and the rights it had to push to my org.</p><p>I spent a lot of time trying different tokens and tweaking settings on GitHub.<br>To no avail.</p><p>The 403 error really misled me into looking for token issues, but it was actually much simpler: as you might have noticed, I was pushing to <code>techtrails/real-emails</code>, whereas my GitHub org name is <code>techtrails-io</code>.</p><p>Yeah, <code>techtrails</code> was already taken :(</p><p>Kamal generates the push URL from the <code>image</code> setting in the <em>deploy.yml</em> file:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y7PI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y7PI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 424w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 848w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 1272w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y7PI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png" width="1442" height="306" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:306,&quot;width&quot;:1442,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42389,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Y7PI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 424w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 848w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 1272w, https://substackcdn.com/image/fetch/$s_!Y7PI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60d9432-5e36-4e90-95fb-b6cb24b8fc52_1442x306.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>So I changed <code>techtrails</code> into <code>techtrails-io</code>, and it worked!</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!s86K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!s86K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 424w, https://substackcdn.com/image/fetch/$s_!s86K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 848w, https://substackcdn.com/image/fetch/$s_!s86K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 1272w, https://substackcdn.com/image/fetch/$s_!s86K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!s86K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png" width="1442" height="298" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:298,&quot;width&quot;:1442,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42884,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!s86K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 424w, https://substackcdn.com/image/fetch/$s_!s86K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 848w, https://substackcdn.com/image/fetch/$s_!s86K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 1272w, https://substackcdn.com/image/fetch/$s_!s86K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4c221c3-0d5d-48b6-93ae-556892711aed_1442x298.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techtrails.io/subscribe?"><span>Subscribe now</span></a></p><h1>TLS and CloudFlare</h1><p>At this point, I had my app successfully deployed to <a href="https://real-emails.com">real-emails.com</a>.<br>It's there, you can check!</p><p>There were a few things, SSL/TLS-wise, that were not 100% satisfying.</p><h2>TLS termination point &amp; redirection loop</h2><p>I'm using CloudFlare as my DNS server, taking advantage of their Proxy feature that serves my site through their own infrastructure, allowing them to cache content at the edge, detect DDoS attacks, etc.</p><p>They also provide automated TLS certificates out-of-the-box, which is great.<br>To make this simple for everyone, the way it works is that their servers act as a TLS termination point:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gH4M!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gH4M!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 424w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 848w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 1272w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gH4M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png" width="1002" height="292" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:292,&quot;width&quot;:1002,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gH4M!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 424w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 848w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 1272w, https://substackcdn.com/image/fetch/$s_!gH4M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7e8d07c-2770-4c62-b0dd-a4f18eb6d80e_1002x292.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As illustrated above, a request coming from a client will be encrypted only between the browser and CloudFlare&#8217;s servers. CloudFlare relays the request to my servers in plain HTTP, without TLS encryption.</p><p>With a Rails application, what this causes when you load your website is an redirection loop, because Rails is configured to force SSL connections by default:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HniB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HniB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 424w, https://substackcdn.com/image/fetch/$s_!HniB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 848w, https://substackcdn.com/image/fetch/$s_!HniB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 1272w, https://substackcdn.com/image/fetch/$s_!HniB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HniB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png" width="728" height="206.9902912621359" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:410,&quot;width&quot;:1442,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:66989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HniB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 424w, https://substackcdn.com/image/fetch/$s_!HniB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 848w, https://substackcdn.com/image/fetch/$s_!HniB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 1272w, https://substackcdn.com/image/fetch/$s_!HniB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0fdab3d-d414-476b-a25b-29de34dc46a1_1442x410.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>So when CloudFlare relays the browser&#8217;s request to Rails as an HTTP request, Rails responds with an HTTP Redirect from http://real-emails.com to https://real-emails.com.<br>This triggers a reloading of the HTTPS URL by the browser, which again is responded to with a redirect&#8230; and thus the loop begins.</p><p>My first fix to this issue was to turn <code>config.force_ssl</code> to <code>false</code>. Easy!</p><p>This, however, feels hacky and suboptimal. Plus it caused another issue that I forgot to note down.<br>And, I do want end-to-end encryption between the browser and my server.</p><p>So what I really want is &#8230;</p><h2>CloudFlare &#8220;Full (strict)&#8221; encryption mode</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Bt4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Bt4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 424w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 848w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 1272w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Bt4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png" width="1028" height="292" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:292,&quot;width&quot;:1028,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31302,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8Bt4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 424w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 848w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 1272w, https://substackcdn.com/image/fetch/$s_!8Bt4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1e07f54-e0eb-4d67-9d82-780bd7d33a06_1028x292.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In this mode, you get end-to-end encryption <em>and</em> a certificate provided by CloudFlare that allows them to certify they're talking to your origin server.</p><p>I think I'll write a specific tutorial to configure Kamal for this setup, but here&#8217;s the gist of it:</p><ul><li><p>Store CloudFlare certificate on your server</p></li><li><p>Declare a Docker volume for the Traefik service to get access to this certificate and am accompanying TLS config file</p></li><li><p>Configure a TLS entryPoint on Traefik and route it to your app&#8217;s service</p></li></ul><p><a href="https://traefik.io/">Traefik</a> is the reverse proxy Kamal is built upon to route requests to your application. In CloudFlare&#8217;s Full (strict or not) encryption mode, it's Traefik that becomes the TLS termination point, right before Rails serves your app.</p><p>So what you have to do, as outlined above, is just to provide it with the right TLS certificate and be done.<br>It&#8217;s even easier if you don't aim for strict mode (but I thought, let's go all the way!) since Traefik can provision certificates for you with Let's Encrypt.</p><p>Anyway. The simple yet terrible mistake I made here is that &#8220;Traefik&#8221; is simply the phonetics transcription of &#8220;traffic&#8221;, and some muscle memory at some point made me write &#8220;traefi<strong>c</strong>&#8221; in the Docker volume name configuration &#129318;&#8205;&#9794;&#65039;</p><p>Only after I left the broken site for a night and came back to it with fresh eyes and a thorough review of Traefik logs (which only indicated it hadn't found any certificate) did I understand my mistake.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Get those tech insights and tutorials right into your inbox: subscribe!</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h1>Bonus: conflict with foreman</h1><p>As an added bonus, I finally faced a seemingly unrelated issue when I got back to developing locally.</p><p>Since I'm using TailwindCSS, I have the cssbundling gem installed to rebuild my styles as I add new Tailwind classes to my templates.<br>This is handled by a separate process, so I'm using the provided <code>bin/dev</code> command instead of running <code>rails server</code>.</p><p><code>bin/dev</code> is provided by the gem, and simply uses <a href="https://github.com/ddollar/foreman">foreman</a> to run both <code>rails server</code> and <code>rails tailwindcss:watch</code> in parallel.</p><p>What happened after I had completed my Kamal setup, is that:</p><ul><li><p>running <code>rails server</code> would work just fine</p></li><li><p>running <code>bin/dev</code> would see the <code>rails server</code> process fail with an error: <code>ActiveSupport::MessageEncryptor::InvalidMessage</code></p></li></ul><p>This error generally occurs when Rails, upon booting, is not able to decrypt the <em>credentials.yml.enc</em> file that contains the <code>secret_base</code> token and other credentials you might have stored there.</p><p>It made no sense though, that it would work when run alone and fail when run through foreman.</p><p>To figure out what was going on, I edited Rails core files to place a debugger instruction right before the code that would throw the <code>ActiveSupport::MessageEncryptor::InvalidMessage</code> exception.</p><p>This allowed me to run rdbg (a command-line Ruby debugger) and attach to the process, which in turn let me inspect live variables content and see what the process was dealing with when crashing.</p><p>This is the code I dove into:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!czY2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!czY2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 424w, https://substackcdn.com/image/fetch/$s_!czY2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 848w, https://substackcdn.com/image/fetch/$s_!czY2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 1272w, https://substackcdn.com/image/fetch/$s_!czY2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!czY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png" width="1456" height="1491" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1491,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:343042,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!czY2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 424w, https://substackcdn.com/image/fetch/$s_!czY2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 848w, https://substackcdn.com/image/fetch/$s_!czY2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 1272w, https://substackcdn.com/image/fetch/$s_!czY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13a1e978-ec65-43da-a8cb-8b9042dfc629_1594x1632.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>From <code>decrypt_and_verify</code>, in which the first <code>catch_and_raise</code> method was the one ultimately causing the crash, I could verify that the <code>message</code> argument contained the encrypted content of my development <em>credentials.yml.enc</em> file.<br>As I would expect in this context.</p><p>Later on, the <code>read_message</code> call leads to the <code>decrypt</code> method.<br>In there, I inspected the <code>@secret</code> instance variable, and found that it contained my <em><strong>production</strong></em> encryption key.</p><p>No surprise it couldn't correctly decrypt the file!</p><p>Now the question was: how did Rails, started in development mode, was picking up the production key instead of the development one?</p><p>After some thinking and digging, I inspected the content of <code>ENV["RAILS_MASTER_KEY&#8220;]</code>, which is one way for Rails to get the decryption key.<br>It was indeed set to the production key.</p><p>That's when I realized what was going on:</p><ul><li><p><strong>One one hand:</strong><br>When initializing Kamal, it creates a <em>.env</em> file into which you can provide environment variables for your deployment.<br>If you recall from the beginning of this article, this is where the <code>KAMAL_REGISTRY_PASSWORD</code> value comes from.<br><br>The other value that you <em>need</em> to put there, is the <code>RAILS_MASTER_KEY</code> encryption key, so that Kamal can set it on the deployed container for Rails to boot correctly.</p></li><li><p><strong>On the other hand:<br></strong>Foreman, used in the <code>bin/dev</code> script, will by default load environment variables for the spawned processes from any <em>.env</em> file it can find in its working directory.<br>So it picks up the one from Kamal, and &#8220;corrupts&#8221; your local process with environment variables meant for production.</p></li></ul><p>It's hard to tell whether Kamal or Foreman is at fault here, but once I understood the issue I quickly found a PR on GitHub that addressed the problem: <a href="https://github.com/rails/cssbundling-rails/pull/155">Disable loading .env file when running foreman for development</a>.</p><p>Simply tell foreman to load environment variables from <em>/dev/null</em> (or another arbitrary file if needed) in the <code>bin/dev</code> script:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4OTb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4OTb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 424w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 848w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 1272w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4OTb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png" width="864" height="88" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:88,&quot;width&quot;:864,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16420,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4OTb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 424w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 848w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 1272w, https://substackcdn.com/image/fetch/$s_!4OTb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbc5b690-bfee-4cad-ac87-087d9906e2bd_864x88.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h1>The end.</h1><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/p/down-the-kamal-rabbit-holes?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading it all! If you liked this post, please share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/p/down-the-kamal-rabbit-holes?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techtrails.io/p/down-the-kamal-rabbit-holes?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div>]]></content:encoded></item><item><title><![CDATA[Adding subscribers to Substack]]></title><description><![CDATA[Or dealing with sunk costs and escalation of commitment...]]></description><link>https://techtrails.io/p/adding-subscribers-to-substack</link><guid isPermaLink="false">https://techtrails.io/p/adding-subscribers-to-substack</guid><dc:creator><![CDATA[Olivier Lance]]></dc:creator><pubDate>Sat, 06 Jul 2024 21:02:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pEDW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pEDW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pEDW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 424w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 848w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 1272w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pEDW!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:610,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3537396,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pEDW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 424w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 848w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 1272w, https://substackcdn.com/image/fetch/$s_!pEDW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46602c1b-4ca4-4718-8be0-9c37f9df21dc_2000x838.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="pullquote"><p>This is a post from my Tech Journal section, in which I dive into technical topics, focusing on how I overcome specific challenges.<br>If you're not into the tech stuff, you can unsubscribe from Tech Journal updates from <a href="https://techtrails.io/account">your account</a>.</p></div><p>My build in public journey starts with technical challenges on stuff I wouldn't want to have to deal with&#8230;<br>I'm probably going down a rabbit hole here, but I hope I&#8217;ll be out of it soon.</p><p>The thing is, I have already invested <em>some </em>money in both Carrd &amp; Substack, and I'd like the setup to work. Because I <em>invested </em>in it, right?<br>Right.</p><p>Check out the concept of <a href="https://en.wikipedia.org/wiki/Sunk_cost">sunk costs</a> or <a href="https://en.wikipedia.org/wiki/Escalation_of_commitment">escalation of commitment</a> if you want to understand the dilemma I'm in &#128517;</p><p>Anyway.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Techtrails! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>So, I've decided to use <a href="https://try.carrd.co/techtrails">Carrd.co</a> to quickly build the landing page for my projects, and Substack to power my newsletter.</p><p>The issue is: since Substack has no public API, there&#8217;s no way to register subscribers on Substack from Carrd forms.</p><h1>SubstackAPI.com</h1><p>While searching for a potential solution, I stumbled upon <a href="https://substackapi.com">SubstackAPI.com</a>.</p><p>I've tried using their solution, but it ended up not working after a short while and I'm not sure why. The author's account is not very active, so I'm going to assume their service is broken&#8230;</p><p>Which leaves me no choice but to figure it out myself.</p><h1>All by myself</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oTcn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oTcn!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 424w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 848w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 1272w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oTcn!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif" width="480" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Ill Do It Myself Season 4 GIF by The Office&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Ill Do It Myself Season 4 GIF by The Office" title="Ill Do It Myself Season 4 GIF by The Office" srcset="https://substackcdn.com/image/fetch/$s_!oTcn!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 424w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 848w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 1272w, https://substackcdn.com/image/fetch/$s_!oTcn!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73f78ac0-6dd5-4ecf-bc02-51801e1ad6f6_480x400.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Substack <em>does</em> have an API to register new subscribers. It's just not public.<br>So I'm taking my chances trying to use it myself, and I'm guessing that's just what substackapi.com did initially.</p><h2>How Substack does it</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5k0-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5k0-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 424w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 848w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 1272w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5k0-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png" width="318" height="279.45454545454544" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:754,&quot;width&quot;:858,&quot;resizeWidth&quot;:318,&quot;bytes&quot;:127732,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5k0-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 424w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 848w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 1272w, https://substackcdn.com/image/fetch/$s_!5k0-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2607e63f-d47a-46d8-9c76-c47264b5be07_858x754.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Using the &#8220;splash screen&#8221; subscription form for my publication allowed me to get the details of the API call they're making to their servers to add a new subscriber. Here it is as a <code>cURL</code> command:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!A93C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!A93C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 424w, https://substackcdn.com/image/fetch/$s_!A93C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 848w, https://substackcdn.com/image/fetch/$s_!A93C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!A93C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!A93C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png" width="1456" height="1013" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1013,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:303406,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!A93C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 424w, https://substackcdn.com/image/fetch/$s_!A93C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 848w, https://substackcdn.com/image/fetch/$s_!A93C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!A93C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a9238e-85b1-4309-8952-0c4d68989d5f_1724x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The important part is of course the JSON data at the end of the command, but interestingly Substack will not process the subscriber when I remove too much of the headers.</p><p>With trial and error, I got the request stripped down to:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uy8r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uy8r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 424w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 848w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 1272w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uy8r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png" width="1456" height="665" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:665,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:211550,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uy8r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 424w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 848w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 1272w, https://substackcdn.com/image/fetch/$s_!uy8r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed3a23e-ac58-49cf-8054-1c675b0a72fe_1744x796.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Surprisingly, the <code>user-agent</code> header is required for the email to be sent. I guess it's one of their heuristics to prevent server-to-server signups &#129300;</p><p>The <code>origin</code> header is also definitely used to check where the request is coming from and reject unrecognized sources. Since browsers won't let you override this header in JavaScript <code>fetch</code> requests, it's a good filter for blocking rogue forms from external sources.<br>However it does mean that I'll have to send the request from a server for things to work.</p><h2>Making the call</h2><h3>Using Carrd&#8217;s custom form handler</h3><p>It's possible, using Carrd, to directly address a remote server with a custom JSON payload. What's nice is, they make the API call from their own servers.<br>So I wouldn't have anything to code or host if it works!</p><p>I have dropped the <code>accept</code> and <code>content-type</code> headers as I suppose they'll be added by Carrd:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!I7uU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!I7uU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 424w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 848w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 1272w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!I7uU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png" width="318" height="661.9111111111112" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1686,&quot;width&quot;:810,&quot;resizeWidth&quot;:318,&quot;bytes&quot;:206503,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!I7uU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 424w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 848w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 1272w, https://substackcdn.com/image/fetch/$s_!I7uU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57ef4951-487d-4c64-8cdf-30ee5712be31_810x1686.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It took me 2 minutes to set this up on my Carrd form. Will it work?</p><p>&#128073; Hit save<br>&#128073; Open landing page<br>&#128073; Enter email &amp; click &#8220;get updates&#8221; &#8230;<br>&#129345;<br>&#129431;&#129431;&#129431;</p><p>The call seems to have been successful, but I do not receive any subscription confirmation email from Substack.</p><p>Let's investigate!</p><p>As Carrd is sending the request from their servers, I cannot debug the API call from my browser. Using <a href="https://beeceptor.com/">Beeceptor</a>, I setup a mock endpoint to send the requests to, and inspect what data and headers Carrd is sending.</p><p>Here are the headers:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5Opx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5Opx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 424w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 848w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 1272w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5Opx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png" width="728" height="296.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:593,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:157612,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5Opx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 424w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 848w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 1272w, https://substackcdn.com/image/fetch/$s_!5Opx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d0651f5-231b-49bc-8c03-37cb5a8461b2_1840x750.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Both the <code>referer</code> and <code>origin</code> headers have been removed from the request. Damn.<br>Why would they do that I don&#8217;t know, but I'll have to use another method.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">If you love nothing more than reading a dev over-engineer a form subscription, subscribe!</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><h3>Plan B: all by myself, again</h3><p>Plan B is quite simple: receive the form data from Carrd on a custom endpoint, and forward the subscription to Substack.</p><p>Since my techtrails.io domain is hosted at Cloudflare, I'm going to use their <a href="https://workers.cloudflare.com/">Workers</a> feature to get this done quickly. I had never used Cloudflare as a development platform, and I'm surprised at how easy it is to get something up live!</p><p>All it takes is:</p><pre><code>npm create cloudflare@latest</code></pre><p>Then follow the instructions, log into my Cloudflare account and voil&#224;! I have a running worker online.</p><p>Here&#8217;s the meaty part of what I deployed:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Pn6C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Pn6C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 424w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 848w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 1272w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Pn6C!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png" width="1200" height="1927.7472527472528" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:2339,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:583639,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Pn6C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 424w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 848w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 1272w, https://substackcdn.com/image/fetch/$s_!Pn6C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b169a5-7b6e-4d9c-bcf6-dab92fdd0af8_1840x2956.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Deploying the new code is just a <code>npm run deploy</code> away, and I&#8217;m able to test the endpoint using the automated Swagger UI &#128077;</p><p>Aaaaand&#8230; it does not work.</p><p>I mean, the code works all right, it's pretty simple.<br>But Substack still completely ignores the subscriber request, even though it does respond with an <code>HTTP 200</code> and returns some JSON payload response.</p><p>Using Beeceptor again as the target for this <code>fetch</code> request, I can see that everything is all right from a headers point of view.</p><p>Next, I just launched the <code>node</code> REPL from my machine and pasted the above fetch request into it.</p><p>It works! &#129327;<br>With the <em>exact. same. code.</em></p><p>So now I'm wondering whether they could be identifying that I'm calling them from a Cloudflare worker.<br>Another test from a VPS server led to the same result.<br>Could they be checking the originating IP address for well-known hosting providers?</p><p>Hard to know for sure, but it looks like the server-to-server calls are getting too complicated.</p><h3>Plan C: it's all about <code>origin</code></h3><p>Call me stubborn, but I&#8217;ve got another trick up my sleeve.</p><p>The one thing I&#8217;m sure they won&#8217;t be filtering out is requests coming <em>from a browser</em> and <em>originating from techtrails.io.</em></p><p>I've got one way to pull this out: iframe.</p><p>Cloudflare is an amazing tool. I can use it to re-route some traffic for my techtrails.io domain to a Worker, while letting the rest through to Substack.</p><p>I'm going to host a small HTML page on Cloudflare with some JS code that will send the subscription API call to Substack, and embed this into an iframe on my Carrd landing page.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vaet!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vaet!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 424w, https://substackcdn.com/image/fetch/$s_!vaet!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 848w, https://substackcdn.com/image/fetch/$s_!vaet!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 1272w, https://substackcdn.com/image/fetch/$s_!vaet!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vaet!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png" width="1456" height="519" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:519,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:185645,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vaet!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 424w, https://substackcdn.com/image/fetch/$s_!vaet!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 848w, https://substackcdn.com/image/fetch/$s_!vaet!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 1272w, https://substackcdn.com/image/fetch/$s_!vaet!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f3ec794-129a-4853-8292-92ce7d7cf8fb_2176x776.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>With some cross-frame communication, I can trigger the subscription API call from my Carrd site but with Techtrails as the effective origin, and all should work.</p><p>Let's get to it!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OePE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OePE!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 424w, https://substackcdn.com/image/fetch/$s_!OePE!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 848w, https://substackcdn.com/image/fetch/$s_!OePE!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 1272w, https://substackcdn.com/image/fetch/$s_!OePE!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OePE!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif" width="592" height="450" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:450,&quot;width&quot;:592,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;alice in wonderland GIF by Disney&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="alice in wonderland GIF by Disney" title="alice in wonderland GIF by Disney" srcset="https://substackcdn.com/image/fetch/$s_!OePE!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 424w, https://substackcdn.com/image/fetch/$s_!OePE!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 848w, https://substackcdn.com/image/fetch/$s_!OePE!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 1272w, https://substackcdn.com/image/fetch/$s_!OePE!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b66e629-d3cb-4662-abe8-223d635653ed_592x450.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>On the Cloudflare side</h4><p>I'm deploying a new Worker that will route everything to Substack normally, except a specific <code>/substack-subscribers</code> route that will serve my special page:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YWbz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YWbz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 424w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 848w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 1272w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YWbz!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png" width="1200" height="1138.1868131868132" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1381,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:295284,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YWbz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 424w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 848w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 1272w, https://substackcdn.com/image/fetch/$s_!YWbz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88e33678-a608-4ee0-926a-e7fd0391d787_1598x1516.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>One <code>npm run deploy</code> later, and my domain is now serving this special page at <em>techtrails.io/substack-subscribers</em>.</p><p>But what does it contain?<br>Mainly JavaScript:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!31Ah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!31Ah!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 424w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 848w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 1272w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!31Ah!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png" width="1200" height="2260.714285714286" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:2743,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:671116,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!31Ah!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 424w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 848w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 1272w, https://substackcdn.com/image/fetch/$s_!31Ah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68b74d53-50ee-4b42-8bde-d15eeeb1b3f2_1840x3466.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here&#8217;s what the code does in a nutshell:</p><ul><li><p><strong>Lines 14-64:</strong> Set up a listener for the <code>message</code> event and handle two different messages:</p><ul><li><p><code>substack-subscribers:ack</code> &#8212; simply to let the host page (the Carrd site) acknowledge that our iframe script is ready.</p></li><li><p><code>substack-subscribers:subscribe</code> &#8212; to receive, from the host page, the email address that should be sent to Substack.</p></li></ul></li><li><p><strong>Line 67:</strong> Post the <code>substack-subscribers:init</code> message to the host page. This will allow the host page to know which <code>window</code> &amp; <code>origin</code> pair it should send its own messages to.</p></li></ul><p>It will also post either <code>:subscribed</code> or <code>:error</code> messages to bubble up the Substack API call result to Carrd.</p><h4>On Carrd side</h4><p>On my Carrd landing page, I&#8217;m adding an Embed component to inject the following code into my page:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!z3O-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z3O-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 424w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 848w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 1272w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!z3O-!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png" width="1200" height="1715.10989010989" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:2081,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:541104,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!z3O-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 424w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 848w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 1272w, https://substackcdn.com/image/fetch/$s_!z3O-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1641bd6d-8393-453c-a6a8-a1b25e405f12_1840x2630.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This code publishes a global <code>Techtrails.subscribeEmail</code> function (lines 40-50) that will be used by the Carrd custom Form to trigger the API call to Substack via the iframe.</p><p>It also handles the following messages:</p><ul><li><p><strong>Lines 14-22:</strong> <code>substack-subscribers:init</code> &#8211; to auto-discover the Techtrails iframe to which messages should be sent.</p></li><li><p><strong>Lines 25-35:</strong> <code>substack-subscribers:subscribed</code> and <code>:error</code> &#8212; to handle subscription success or error by invoking Carrd&#8217;s callbacks. Those callbacks will in turn trigger the Carrd Form success or failure handlers, for instance to redirect to a success page after form submission.</p></li></ul><p>Another Embed component allows me to inject the iframe that will load my <em>techtrails.io/substack-subscribers</em> page, responsible for communicating with Substack:</p><pre><code>&lt;iframe src="https://techtrails.io/substack-subscribers"&gt;&lt;/iframe&gt;</code></pre><p>Finally, I&#8217;m using a custom Carrd form set to <em>run code</em> upon submission:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tiqS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tiqS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 424w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 848w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 1272w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tiqS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png" width="397" height="741.8972895863053" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1310,&quot;width&quot;:701,&quot;resizeWidth&quot;:397,&quot;bytes&quot;:105846,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tiqS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 424w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 848w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 1272w, https://substackcdn.com/image/fetch/$s_!tiqS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b794ed-731f-420c-89c1-045db1483ee2_701x1310.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The code calls my <code>subscribeEmail</code> function defined earlier, passing in the email to be subscribed and the <code>success</code> and <code>failure</code> callbacks to notify Carrd of submission completion.</p><p>Ok now. Save &amp; publish.</p><h2>The final test</h2><p>Looks like my last idea was the one :)</p><p>Shortly after submitting the form on my landing page, I received the following email:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YzbA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YzbA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 424w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 848w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 1272w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YzbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png" width="398" height="362.28205128205127" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1065,&quot;width&quot;:1170,&quot;resizeWidth&quot;:398,&quot;bytes&quot;:128588,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YzbA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 424w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 848w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 1272w, https://substackcdn.com/image/fetch/$s_!YzbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb7f74b-4fe7-4a54-bfdc-8baedde72365_1170x1065.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>&#129395;</p><h1>Out of the rabbit hole</h1><p>Et voil&#224;.<br>It was quite a journey to make this work!</p><p>Thank you for reading the whole thing.</p><p>I honestly wouldn&#8217;t have liked to rethink my whole landing page + newsletter setup, especially since I do appreciate Substack as a platform but the landing page design is quite limited.</p><p>However, I can&#8217;t help but feel that being a software engineer can sometimes be a curse in disguise: <em>coding is a superpower I&#8217;m often tempted to use instead of looking for simpler solutions.</em></p><p>It&#8217;s definitely something I&#8217;ll have to be careful about on my journey to build myself a portfolio of side projects.</p><p>What about you? How often do you overdo stuff because you know you can do it?</p><p>Do let me know how you liked this deep dive into bypassing Substack&#8217;s (quite advanced) filters!</p>]]></content:encoded></item><item><title><![CDATA[Installing Rails from scratch]]></title><description><![CDATA[Going back to my roots]]></description><link>https://techtrails.io/p/installing-rails-from-scratch</link><guid isPermaLink="false">https://techtrails.io/p/installing-rails-from-scratch</guid><dc:creator><![CDATA[Olivier Lance]]></dc:creator><pubDate>Sun, 16 Jun 2024 13:39:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!cm0g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cm0g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cm0g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 424w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 848w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 1272w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cm0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png" width="500" height="483" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:483,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12576,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cm0g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 424w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 848w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 1272w, https://substackcdn.com/image/fetch/$s_!cm0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5be26e0b-0a39-4bab-9139-d0b3712e09bf_500x483.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I have been a Ruby on Rails fan for a very long time.</p><p>Unfortunately, my career track did not lead me to use it professionally, so it turns out I haven't touched Rails since its &#8230; 3rd version &#129394;</p><p>Now that I am back to building personal projects, I've decided to pick up Rails again.</p><p>Meaning I have to install the entire stack from scratch, so here are the notes to achieve that<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>:</p><h3>1. Install Ruby via rbenv</h3><p>Looks like the landscape hasn't changed here and it's still RVM vs. rbenv!</p><p>I'm choosing rbenv for&#8230; reasons (mainly because it doesn&#8217;t mess with the environment/standard commands so much):</p><pre><code><code>$ brew install rbenv </code></code></pre><p>Once installed, I can learn that the latest stable Ruby version is now 3.3.3:</p><pre><code>$ rbenv install -l
3.1.6
3.2.4
3.3.3
jruby-9.4.7.0
mruby-3.3.0
picoruby-3.0.0
truffleruby-24.0.1
truffleruby+graalvm-24.0.1

Only latest stable releases for each Ruby implementation are shown.
Use `rbenv install --list-all' to show all local versions.</code></pre><p>So let&#8217;s install it!</p><pre><code>$ rbenv install 3.3.3</code></pre><p>And make it the global Ruby version for my system:</p><pre><code>$ rbenv global 3.3.3</code></pre><p>For everything to work, don't forget to add the following to <code>~/.zshrc</code>:</p><pre><code>eval "$(rbenv init - zsh)"</code></pre><h3>2. Install Rails</h3><p>As easy as it gets:</p><pre><code>$ gem install rails</code></pre><p>And voil&#224; ! Ready to go &#128077;</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techtrails.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">I'm writing up small tips like this one as I progress through my projects. Subscribe to get more!</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>On macOS, using Homebrew, and ZSH as shell</p></div></div>]]></content:encoded></item></channel></rss>