<?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[CodeBitz’s Substack]]></title><description><![CDATA[My personal Substack]]></description><link>https://codebitz.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!ekDb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1734a05d-483b-47b6-9577-73d34c65eb8c_144x144.png</url><title>CodeBitz’s Substack</title><link>https://codebitz.substack.com</link></image><generator>Substack</generator><lastBuildDate>Sun, 05 Apr 2026 21:34:37 GMT</lastBuildDate><atom:link href="https://codebitz.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[CodeBitz]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[codebitz@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[codebitz@substack.com]]></itunes:email><itunes:name><![CDATA[Shay Doherty]]></itunes:name></itunes:owner><itunes:author><![CDATA[Shay Doherty]]></itunes:author><googleplay:owner><![CDATA[codebitz@substack.com]]></googleplay:owner><googleplay:email><![CDATA[codebitz@substack.com]]></googleplay:email><googleplay:author><![CDATA[Shay Doherty]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Notifications Are the New Cigarettes: Why the Digital Age Needs Law, Not Just Willpower]]></title><description><![CDATA[Abstract]]></description><link>https://codebitz.substack.com/p/notifications-are-the-new-cigarettes</link><guid isPermaLink="false">https://codebitz.substack.com/p/notifications-are-the-new-cigarettes</guid><dc:creator><![CDATA[Shay Doherty]]></dc:creator><pubDate>Sat, 10 May 2025 12:27:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2lDU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.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_!2lDU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2lDU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2lDU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png" width="1024" height="1536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:1536,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3302277,&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_!2lDU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!2lDU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5f94dd1-2bc9-4da0-b5b4-f0f8c1fb16e5_1024x1536.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></p><h5>Abstract </h5><p>First it was cigarettes. Then seatbelts. Now, it&#8217;s push notifications, infinite scroll, and algorithmic feeds&#8212;tools designed to hijack attention faster than the law can catch up.</p><p>We've been here before. Big Tobacco sold addiction as freedom. Car makers dismissed seatbelts as overreach. Today, tech platforms follow a similar script: profit first, responsibility later. Meanwhile, our mental space is under siege.</p><p>This isn't about self-control. It's about cognitive sovereignty&#8212;the right to mental space free from engineered interference. Just as clean air and road safety became public responsibilities, so must our ability to focus, rest, and think clearly.</p><p></p><h2>Notifications Are the New Cigarettes</h2><p>Push alerts aren&#8217;t there to inform. They&#8217;re there to interrupt&#8212;to trigger, to bait, to pull you back in. Even the now-dated &#8220;150 phone checks per day&#8221; figure points to a deeper truth: compulsive attention loops are the norm, not the exception.</p><p>We regulate nicotine because it's addictive and harmful. Why do we allow the same logic to shape every app in a child&#8217;s pocket?</p><h2>From Optimization to Oversight</h2><p>There&#8217;s no &#8220;natural stopping point&#8221; in most digital platforms. Infinite scroll, autoplay, algorithmic curation&#8212;they all mimic slot machines. This isn&#8217;t just distraction. It&#8217;s entrapment.</p><p>We don&#8217;t just need better habits. We need better rules:</p><p>Scroll limits: Cap algorithmic feeds at 30 minutes per app, enforced at the OS level.</p><p>Notification quotas: Make attention-safe defaults the norm.</p><p>Mandatory quiet hours: Require overnight digital downtime, as France does in schools.</p><p>When GDPR launched, it was derided as bureaucratic. But it worked. It reduced data misuse and reshaped norms. We can&#8212;and must&#8212;do the same for attention.</p><p></p><h2>Protecting the Next Generation</h2><p>A 12-year-old&#8217;s brain shouldn&#8217;t be a testing ground for TikTok&#8217;s algorithm. Yet 89% of teens have unrestricted access to platforms optimised for compulsive use.</p><p>California has proposed limits on algorithmic feeds for under-13s. Finland has introduced screen-free school days. The UK already restricts phones in classrooms. Northern Ireland could easily follow&#8212;and lead.</p><p>We could go further: fund phone-free libraries, parks, youth centres. Make space for boredom, focus, conversation.</p><p>Critics say it&#8217;s overreach. But they said the same about seatbelts. Today, seatbelts save over 15,000 lives a year in the U.S., and around 2,000 in the UK. Regulation works.</p><p></p><h2>The Firehose Must Be Throttled</h2><p>We&#8217;ve normalised cognitive overwhelm. Whether or not multitasking &#8220;drops IQ&#8221; is debated&#8212;but the erosion of memory, focus, and clarity isn&#8217;t.</p><p>To reverse the tide, we need:</p><p>International standards for humane design, led by global forums like the UN Internet Governance Forum.</p><p>Transparency on tech lobbying, especially from firms working to block youth safety measures.</p><p>This isn&#8217;t a tech issue. It&#8217;s a civic one.</p><p></p><h2>A Manifesto for Cognitive Sovereignty </h2><p>This isn&#8217;t anti-tech. It&#8217;s pro-human. Just as Silent Spring catalysed environmental reform, we need a new framework&#8212;one that protects attention, empathy, and presence from being monetised out of existence.</p><p>The revolt won&#8217;t go viral. It will be quiet, slow, and gloriously unoptimised. It will look like boredom, stillness, and the freedom to think.</p><p>And like seatbelts, it may be inconvenient&#8212;but it could save lives, one quiet decision at a time.</p><p></p><p>Civilization thrives when law restrains exploitation. Our minds deserve no less.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Building a Minimal Web API in ASP.NET Core 7 with clear separation of concerns]]></title><description><![CDATA[Building a minimal user web api with Entity Framework and SQLite on ASP.NET Web API Core 7]]></description><link>https://codebitz.substack.com/p/building-a-minimal-web-api-in-aspnet</link><guid isPermaLink="false">https://codebitz.substack.com/p/building-a-minimal-web-api-in-aspnet</guid><dc:creator><![CDATA[Shay Doherty]]></dc:creator><pubDate>Tue, 27 Jun 2023 16:45:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Z9Zu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating an api with .NET Core 7 is a great dev experience. Using SQLite as the local database, and Entity Framework Core as the object-database mapper makes it even better. Below are some steps I took to get this minimal api up and running. I've included a handy diagram to help visualize the structure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z9Zu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 424w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 848w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 1272w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png" width="1195" height="1149" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1149,&quot;width&quot;:1195,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1276029,&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_!Z9Zu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 424w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 848w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.png 1272w, https://substackcdn.com/image/fetch/$s_!Z9Zu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57840918-dbc8-4177-b20d-c3bffa3ab15c_1195x1149.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><h2>Repo</h2><p><a href="https://github.com/shaydoc/minimal-api-dotnet">https://github.com/shaydoc/minimal-api-dotnet</a></p><h2>Directory Structure</h2><pre><code>.
&#9500;&#9472;&#9472; /                      # Root directory
&#9500;&#9472;&#9472; Program.cs             # Main entry point for the application
&#9500;&#9472;&#9472; /ef                    # Dir for Entity Framework related files
&#9474;   &#9492;&#9472;&#9472; UserContext.cs       # EF Core DB Context for User
&#9500;&#9472;&#9472; /endpoint              # Dir for API endpoints
&#9474;   &#9492;&#9472;&#9472; UserEndpoint.cs      # API endpoint for User
&#9500;&#9472;&#9472; /Migrations            # Dir for database migration scripts
&#9500;&#9472;&#9472; /poco                  # Dir for Plain Old CLR Objects (POCOs) or simple entities
&#9474;   &#9500;&#9472;&#9472; User.cs              # POCO class for User
&#9474;   &#9492;&#9472;&#9472; UserValidator.cs     # Class for User validation
&#9500;&#9472;&#9472; /repository            # Dir for repository classes
&#9474;   &#9500;&#9472;&#9472; IUserRepository.cs  # Interface for User repository
&#9474;   &#9492;&#9472;&#9472; UserRepository.cs   # Class implementing User repository
&#9500;&#9472;&#9472; /services              # Dir for service classes
&#9474;   &#9500;&#9472;&#9472; IUserService.cs     # Interface for User service
&#9474;   &#9492;&#9472;&#9472; UserService.cs      # Class implementing User service
&#9492;&#9472;&#9472; /wwwroot               # Root Dir for static files
    &#9492;&#9472;&#9472; /content           # Dir for content files
        &#9492;&#9472;&#9472; /data          # Dir for database files
            &#9492;&#9472;&#9472; user.db    # SQLite database file for User</code></pre><h2>API Explorer</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7Jei!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7Jei!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 424w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 848w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 1272w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7Jei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png" width="1456" height="938" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:938,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:201400,&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;: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_!7Jei!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 424w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 848w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 1272w, https://substackcdn.com/image/fetch/$s_!7Jei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f87e5b1-057b-427e-b50c-fdd8cee31a70_2194x1414.png 1456w" sizes="100vw"></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></p><p></p><h2>Setting Up Your Environment</h2><p>Before we get started, you need to ensure that you have .NET Core installed on your machine. If you haven't done so, you can download and install it from the <a href="https://dotnet.microsoft.com/en-us/download">official site</a>. </p><p>Once installed, you can download the repo here, and you can run the API from this directory by using the command:</p><pre><code>dotnet watch run</code></pre><h2>Adding Dependencies</h2><p>For this API service, we require several packages, which we'll use with .NET 7 to set up SQLite. We'll install these packages using the `dotnet add package` command:</p><pre><code> # SQLite
 $: dotnet add package Microsoft.Data.Sqlite

 # Entity Framework Adapter for SQLite
 $: dotnet add package Microsoft.EntityFrameworkCore.Sqlite

 # Entity Framework Core Design for Migrations
 $: dotnet add package Microsoft.EntityFrameworkCore.Design

 # FluentValidation for Elegant Model Validation
 $: dotnet add package FluentValidation.AspNetCore

 # OpenApi for API Decoration
 $: dotnet add package Microsoft.AspNetCore.OpenApi

 # Swashbuckle for API Documentation
 $: dotnet add package Swashbuckle.AspNetCore</code></pre><h2>Connecting to SQLite</h2><p>Next, we need to define the SQLite connection string in our <strong>appsettings.Development.json</strong> and <strong>appsettings.json</strong> files. Add the following lines:</p><pre><code>"ConnectionStrings": {
  "DefaultConnection": "Data Source=./wwwroot/content/data/user.db"
},</code></pre><p>And then, create a <strong>wwwroot/content/data</strong> directory where the <strong>SQLite</strong> file will be housed.</p><p>For the <strong>minimal-api-dotnet.csproj</strong>, add an <strong>ItemGroup</strong> to ensure that the local SQLite copy does not overwrite the production version.</p><pre><code>&lt;ItemGroup&gt;
   &lt;Content Update="wwwroot\content\**\*" CopyToPublishDirectory="Never" /&gt;
&lt;/ItemGroup&gt;</code></pre><p><strong>Note</strong>: If you're deploying via GitHub Actions using the `uses: actions/upload-artifact@v2` step, be aware that your SQLite DB will be reset.</p><h2>Incorporating Entity Framework Core</h2><p>In our /<strong>ef</strong> directory, we'll create a <strong>UserContext</strong>. This class drives the Entity Framework and contains a <strong>DbSet&lt;User&gt;</strong> for a <strong>User</strong> table with an `Id` and a `Name`. Later on, we'll run a migration script to add an `Email` column.</p><p>To connect the Entity Framework with our SQLite database, add the following to the <strong>Program.cs</strong>:</p><pre><code>using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext&lt;UserContext&gt;(options =&gt;
options.UseSqlite(
     builder.Configuration.GetConnectionString("DefaultConnection")
     )
);

var app = builder.Build();</code></pre><p>We also add the user service, user validator, and the DB context to the dependency injection container:</p><pre><code>// DI the user service, user validator, and the DB context
builder.Services.AddScoped&lt;IUserService, UserService&gt;();
builder.Services.AddScoped&lt;IValidator&lt;User&gt;, UserValidator&gt;();
builder.Services.AddScoped&lt;IUserRepository, UserRepository&gt;();</code></pre><h2>User API Endpoints</h2><p>Creating the user API endpoints is simple. In the <strong>/endpoint</strong> directory, we create a <strong>UserEndpoint</strong> static class to map all the <strong>HTTP methods of the User api</strong>. Then we delegate the incoming requests on to our <strong>Service Layer</strong>, which can be repurposed for other connectors. The Service Layer will apply validation checks using our Fluent Validation prior to delegating on to the repository, which will take responsibility for committing the data to the Database table.</p><p><strong>Endpoint groups</strong> help manage API versioning, while the Fluent API allows easy chaining of features like CORS, authorization, and rate limiting:</p><pre><code>Program.cs

app.MapGroup("/api/v1/users")
    .MapGroupOneUserApi()
    .WithTags("Public");


UserEndpoint.cs

static class UserEndpoint
{
  public static RouteGroupBuilder MapGroupOneUserApi(this RouteGroupBuilder group)
  {
    
    // Do call all data access APIs asynchronously.
    group.MapGet("/", async (IUserService service) =&gt; await service.GetUsersAsync())
    .WithName("List All Users v1")
    .WithOpenApi()
    .Produces&lt;List&lt;User&gt;&gt;(StatusCodes.Status200OK);

     ...
}</code></pre><h2>Database Migrations</h2><p>Migrations are a crucial part of database versioning. For our example, we have already applied migrations to add an <strong>Email</strong> field and make it a required one on the <strong>Users</strong> table. Because we are using POCOs, we only need to add a property to our User.cs business object and the entity framework migration will pick it up</p><pre><code># To add email to the Users table:
$: dotnet ef migrations add AddUserEmail
$: dotnet ef migrations update

# To make email a required field:
$: dotnet ef migrations add UserEmailRequired
$: dotnet ef migrations update</code></pre><p> </p><h2>Testing the API</h2><p>To test the API, use the command <strong>dotnet watch run</strong>.</p><p>For viewing and interacting with the API specification, navigate to <strong>http://localhost:5080/swagger/index.html</strong></p><p>And voil&#224;, you've got your minimal Web API using Entity Framework and SQLite on ASP.NET Web API Core 7 up and running. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Resolving Domain Requests]]></title><description><![CDATA[What's happening when your browser requests www.website.com]]></description><link>https://codebitz.substack.com/p/resolving-domain-requests</link><guid isPermaLink="false">https://codebitz.substack.com/p/resolving-domain-requests</guid><dc:creator><![CDATA[Shay Doherty]]></dc:creator><pubDate>Tue, 20 Jun 2023 16:30:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!62Ng!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Having took some time to watch <a href="https://www.lydiahallie.io/">Lydia Halle&#8217;s</a> <strong>fantastic</strong> <a href="https://frontendmasters.com/courses/web-dev-quiz/">Advanced Web Development Frontend Masters Quiz</a>, I thought I would share some of the learnings. Its features so much good material, I would fully recommend checking it out.</p><p>Resolving DNS is some business, there&#8217;s several things going on when you ask for that website in your browser address bar. The diagram below illustrates this behaviour.  For an even better overview, check out the video <a href="https://frontendmasters.com/courses/web-dev-quiz/q3-resolving-domain-requests/">here</a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!62Ng!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!62Ng!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 424w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 848w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 1272w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!62Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png" width="1456" height="2856" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2856,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:686247,&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_!62Ng!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 424w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 848w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.png 1272w, https://substackcdn.com/image/fetch/$s_!62Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc51ec2e-d2d3-439e-b9de-a67d0e9fe96e_1790x3511.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></p><p>1. Domain Name System (DNS):</p><p>The Domain Name System (DNS) is at the core of resolving domain requests. It is a distributed naming system that enables users to associate domain names with IP addresses. Whenever a user enters a domain name into a web browser, the DNS comes into action to locate the corresponding IP address.</p><p>2. Caching:</p><p>To optimize performance, DNS resolvers often employ caching mechanisms. When a user's device makes a domain request, the resolver first checks its cache to see if it has recently resolved the same domain name. If a match is found, the resolver can skip the time-consuming resolution process and provide the IP address directly.</p><p>3. Recursive DNS Resolution:</p><p>If the domain name is not found in the resolver's cache, it initiates the recursive DNS resolution process. The resolver communicates with authoritative DNS servers to resolve the domain request step by step.</p><p>4. Root DNS Servers:</p><p>The resolver begins by contacting the root DNS servers. These servers store information about the top-level domains (.com, .org, .net, etc.). The root servers respond by providing the IP address of the appropriate top-level domain (TLD) server.</p><p>5. TLD DNS Servers:</p><p>Once the resolver receives the IP address of the TLD server, it sends a query to the corresponding TLD DNS server. For example, if the domain is "example.com," the resolver contacts the .com TLD server. The TLD server then directs the resolver to the authoritative name server responsible for the requested domain.</p><p>6. Authoritative Name Servers:</p><p>At this stage, the resolver reaches the authoritative name server for the requested domain. These servers hold the most up-to-date information about the domain, including the IP address associated with it. The resolver sends a query to the authoritative name server, which responds with the requested IP address.</p><p>7. Returning the IP Address:</p><p>Once the resolver receives the IP address from the authoritative name server, it caches the information for future use and returns the IP address to the user's device. The user's device can now establish a connection with the web server hosting the requested domain, enabling the retrieval of the desired web content.</p><p> </p><p>Resolving domain requests is a complex and vital process that underpins the functionality of the internet. The DNS system, with its distributed architecture, ensures that users can easily access websites by typing in human-readable domain names.  We don&#8217;t typically delve this deep when making websites, but it sure is good to discover the process of how it all works&#8230;.</p><p>Happy Web Developing!! &#128640;</p>]]></content:encoded></item><item><title><![CDATA[Leveraging Reverse Proxies for Scalability, Security, and Performance in Enterprise Cloud Infrastructures]]></title><description><![CDATA[One of the crucial components in modern enterprise application infrastructures is a reverse proxy.]]></description><link>https://codebitz.substack.com/p/leveraging-reverse-proxies-for-scalability</link><guid isPermaLink="false">https://codebitz.substack.com/p/leveraging-reverse-proxies-for-scalability</guid><dc:creator><![CDATA[Shay Doherty]]></dc:creator><pubDate>Thu, 15 Jun 2023 19:07:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ZWiH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article aims to outline what a reverse proxy is, its purpose, and advantages, especially in the context of large-scale enterprise app development. I'll also mention some common reverse proxies and delve into an example using Azure PaaS.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZWiH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZWiH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 424w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 848w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 1272w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZWiH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png" width="321" height="543" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:543,&quot;width&quot;:321,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63702,&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_!ZWiH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 424w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 848w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.png 1272w, https://substackcdn.com/image/fetch/$s_!ZWiH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9b3bde0-c132-4105-b974-2c96179dd76d_321x543.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></p><h2><strong>What is a Reverse Proxy?</strong></h2><p>A reverse proxy is a server that sits between client devices and a web server, forwarding client requests to the web server and returning the server&#8217;s responses back to the clients. It essentially acts as a gateway through which client requests are processed before reaching the web server.</p><p>While a forward proxy acts as an intermediary for client requests (think of it as the client's agent), a reverse proxy is essentially an agent for the server, protecting, controlling, and optimizing access to the server.</p><h2><strong>Common Reverse Proxies</strong></h2><p>There are several popular reverse proxies, such as:</p><ul><li><p>Nginx</p></li><li><p>Apache HTTP Server with mod_proxy</p></li><li><p>HAProxy</p></li><li><p>Microsoft Azure Application Gateway</p></li><li><p>AWS Elastic Load Balancing</p></li><li><p>Traefik</p></li></ul><h2><strong>Purpose and Advantages</strong></h2><h3><strong>1. Load Balancing</strong></h3><p>In large-scale enterprise applications, traffic can be immense. Reverse proxies distribute client requests across multiple servers, thus preventing any single server from getting overwhelmed. This leads to increased responsiveness and availability of applications.</p><h3><strong>2. Security and Anonymity</strong></h3><p>By masking the identity and internal structure of your backend servers, reverse proxies add an extra security layer. This is particularly important to prevent attacks such as DDoS which can be devastating to enterprise infrastructure.</p><h3><strong>3. SSL Termination</strong></h3><p>Handling SSL/TLS encryption and decryption (the process of encoding and decoding SSL/TLS certificates) can be resource-intensive for your backend servers. Reverse proxies can manage this process, known as SSL termination, freeing up resources on backend servers to efficiently handle application requests.</p><h3><strong>4. Caching and Content Compression</strong></h3><p>Reverse proxies can store static content and serve this to the client without forwarding the request to the backend server. This reduces the load on your servers and speeds up content delivery. Content compression can also be handled, which reduces the amount of data transferred over the network.</p><h3><strong>5. Application Firewall</strong></h3><p>Reverse proxies can act as an application firewall, protecting against SQL injection, Cross-site Scripting (XSS), and other web application vulnerabilities.</p><h3><strong>6. Global Server Load Balancing</strong></h3><p>For global enterprises, reverse proxies can route client requests to the closest or most responsive data center. This ensures lower latency and a better user experience.</p><h2><strong>Azure PaaS Example</strong></h2><p>Azure PaaS (Platform as a Service) offers a service called <a href="https://learn.microsoft.com/en-us/azure/application-gateway/overview">Azure Application Gateway</a> which acts as a reverse proxy.</p><p>Suppose you have a large-scale web application with users from across the globe. You have deployed this application in several Azure regions to ensure low latency.</p><ol><li><p><strong>Create the Application Gateway</strong>: In the Azure portal, you can create an Application Gateway and specify the virtual networks your application is a part of.</p></li><li><p><strong>Configure Backend Pools</strong>: Backend pools consist of the web servers that the Application Gateway will distribute traffic to. You can configure these pools with the IP addresses of your web servers across different regions.</p></li><li><p><strong>Configure Routing Rules</strong>: Here, you can specify how the traffic should be distributed. For example, you can use a path-based rule that routes traffic to different pools based on the URL path.</p></li><li><p><strong>SSL Termination</strong>: Import your SSL certificate into the Application Gateway. This offloads the SSL termination process from the web servers.</p></li><li><p><strong>Enable Web Application Firewall</strong>: You can enable the WAF feature on the Application Gateway and choose from a set of predefined rules that protect against common web vulnerabilities or even create custom rules tailored for your application.</p><ol start="6"><li><p><strong>Optimize Content Delivery</strong>: Configure caching within Application Gateway to cache static content. This will make the content readily available for serving, thus reducing the load on your backend servers.</p></li><li><p><strong>Monitor and Diagnose</strong>: Finally, integrate Application Gateway with Azure Monitor. This allows you to monitor the performance and health of your application and gateway, set up alerts, and troubleshoot issues.</p></li></ol><h2><strong>Wrapping Up</strong></h2><p>Incorporating a reverse proxy is a fundamental step in scaling and securing enterprise applications, particularly when they are cloud-based. Through load balancing, enhanced security features, efficient SSL termination, content caching, and global server load balancing, reverse proxies such as Azure Application Gateway in Azure PaaS empower enterprises to build robust, fast, and secure applications. By shielding the internal servers from direct exposure to the internet, they add an essential layer of protection. The benefits they offer are especially critical for large-scale applications that require handling high volumes of traffic while providing an uninterrupted and optimized user experience.</p><p></p></li></ol>]]></content:encoded></item><item><title><![CDATA[Broadcasting Magic Across Tabs with the Broadcast Channels API]]></title><description><![CDATA[Using Broadcast Channels to instantly log out of all Browser Tabs.]]></description><link>https://codebitz.substack.com/p/broadcasting-magic-across-tabs-with</link><guid isPermaLink="false">https://codebitz.substack.com/p/broadcasting-magic-across-tabs-with</guid><dc:creator><![CDATA[Shay Doherty]]></dc:creator><pubDate>Tue, 13 Jun 2023 11:06:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!sNLj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this rapidly evolving web world, it's crucial for applications to communicate effectively. When multiple tabs are open, it's sometimes essential for them to chat. But how can we, as developers, make this happen? Enter the Broadcast Channel API!</p><p>In this post, we will delve into the capabilities of the Broadcast Channel API and put it to practical use by implementing a "log out from all tabs" functionality. So, without further ado, let's dive in!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codebitz.substack.com/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 CodeBitz&#8217;s Substack! 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><h2><strong>What are Broadcast Channels?</strong></h2><p>Broadcast Channels support communication between browsing contexts (such as tabs, windows, or iframes) on the same origin (domain, protocol, and port). It's akin to a magical string attached between different parts of your application, enabling them to send messages to one another. see (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API">Broadcast Channel API on MDN</a>) </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sNLj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sNLj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 424w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 848w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 1272w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sNLj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png" width="492" height="492" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:560,&quot;width&quot;:560,&quot;resizeWidth&quot;:492,&quot;bytes&quot;:36802,&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_!sNLj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 424w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 848w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.png 1272w, https://substackcdn.com/image/fetch/$s_!sNLj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d99ddd-73b5-4d67-a978-5265a7163c76_560x560.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>This API provides a simple and powerful way to communicate between different tabs without the need for complicated setups or server-side help.</p><p></p><h2><strong>Getting Started</strong></h2><p>To create a Broadcast Channel, you create a new <strong>BroadcastChannel</strong> object and give it a name. Any browsing context that creates a <strong>BroadcastChannel</strong> with the same name can communicate with each other!</p><pre><code>const channel = new BroadcastChannel('my_channel');</code></pre><p>Now let's send and receive messages:</p><pre><code>// Sending a message
channel.postMessage('Hello across tabs!');

// Receiving a message
channel.onmessage = (event) =&gt; {
    console.log('Received: ', event.data);
};</code></pre><h2><strong>Logging Out Across All Tabs - A Real-world Scenario</strong></h2><p>Imagine an application where a user is logged in across multiple tabs. When they log out from one tab, it's a best practice to log them out from all the tabs. Let's see how we can do this using the Broadcast Channel API.</p><h3><strong>Step 1: Setup the Broadcast Channel</strong></h3><p>When the user logs in, create a new Broadcast Channel. This can be done in your main JavaScript file or where your application initializes.</p><pre><code>const logoutChannel = new BroadcastChannel('logout_channel');</code></pre><h3><strong>Step 2: Listen for Logout Events</strong></h3><p>On each tab, listen for messages. If a message indicating that the user has logged out is received, perform the logout operation on this tab as well.</p><pre><code>logoutChannel.onmessage = (event) =&gt; {
    if (event.data === 'logout') {
        // Perform the logout operation here
        console.log('Logging out from this tab as well...');
    }
};</code></pre><h3><strong>Step 3: Broadcast the Logout Event</strong></h3><p>When the user initiates a logout in one tab, broadcast this event to all other tabs.</p><pre><code>function userInitiatedLogout() {
    // Perform the logout operation for the current tab
    console.log('User logged out from this tab.');

    // Notify other tabs
    logoutChannel.postMessage('logout');
}</code></pre><p>And that&#8217;s it! Whenever <strong>userInitiatedLogout()</strong> is called in any of the tabs, all other tabs will receive the message and log the user out.</p><h2>Show me it working&#8230;..</h2><p>Below is a small code example in VueJS, you can preview it here: </p><p><a href="https://broadcast-channel-demo.surge.sh">Logout of All Tabs Demo</a></p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;d4ea853c-a740-4534-a87f-900e5a72e08e&quot;,&quot;duration&quot;:null}"></div><pre><code>&lt;template&gt;
  &lt;div id="app"&gt;
    &lt;div v-if="isLoggedIn"&gt;
      &lt;h1&gt;You are logged in&lt;/h1&gt;
      &lt;button @click="userInitiatedLogout"&gt;Log out&lt;/button&gt;
    &lt;/div&gt;
    &lt;div v-else&gt;
      &lt;h1&gt;You are logged out&lt;/h1&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { shallowRef, onMounted, onBeforeUnmount } from 'vue'

// Create a reactive variable to store the login status
const isLoggedIn = shallowRef(true)

// Create a BroadcastChannel to communicate with other tabs
const logoutChannel = new BroadcastChannel('logout_channel')

// Create a function to log the user out
function userInitiatedLogout() {
  isLoggedIn.value = false
  logoutChannel.postMessage('logout')
}

onMounted(() =&gt; {
  // Listen for logout events from other tabs
  logoutChannel.onmessage = (event) =&gt; {
    if (event.data === 'logout') {
      isLoggedIn.value = false
    }
  }
})

onBeforeUnmount(() =&gt; {
  // Close the channel when the component is unmounted
  logoutChannel.close()
})
&lt;/script&gt;

&lt;style&gt;
#app {
  text-align: center;
  margin-top: 60px;
}
&lt;/style&gt;
</code></pre><h2><strong>Closing the Channel</strong></h2><p>Don't forget to close the channel when it's no longer needed, like when the user is logged out, to free up resources.</p><pre><code>logoutChannel.close();</code></pre><h2><strong>Conclusion</strong></h2><p>The Broadcast Channel API offers an elegant and simple way to communicate between browsing contexts on the same origin. As we have seen, it can be incredibly useful for synchronizing actions like logging out from all tabs. With just a few lines of code, you can make your web applications more responsive and user-friendly. </p><p>Happy coding! &#128640;</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codebitz.substack.com/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 CodeBitz&#8217;s Substack! 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>]]></content:encoded></item></channel></rss>