<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sean Boult</title>
    <description>The latest articles on Forem by Sean Boult (@hacksore).</description>
    <link>https://forem.com/hacksore</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F828306%2Fbf0bbed7-7874-4a26-8137-bb761a4b7f23.png</url>
      <title>Forem: Sean Boult</title>
      <link>https://forem.com/hacksore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hacksore"/>
    <language>en</language>
    <item>
      <title>Hide regions and services in the AWS console</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Wed, 15 Apr 2026 21:26:43 +0000</pubDate>
      <link>https://forem.com/aws/hide-regions-and-services-in-the-aws-console-1m09</link>
      <guid>https://forem.com/aws/hide-regions-and-services-in-the-aws-console-1m09</guid>
      <description>&lt;p&gt;Tired of scrolling through regions and services you'll never use?&lt;/p&gt;

&lt;p&gt;You just want to...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbswyi3rgrkoso9ep0f6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbswyi3rgrkoso9ep0f6.png" alt=" " width="576" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS now lets you hide regions and services from your console. Here's how.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Heads up:&lt;/strong&gt; This is a visual preference, not a security control. Users can still access hidden regions and services directly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hide Regions
&lt;/h2&gt;

&lt;p&gt;That region dropdown doesn't need to show every region AWS offers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3lv5j0ibchnon2gu8rp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3lv5j0ibchnon2gu8rp.png" alt=" " width="800" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://us-east-1.console.aws.amazon.com/settings/home?region=us-east-1" rel="noopener noreferrer"&gt;Unified Settings → Account settings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;Visible Regions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Deselect the regions you don't use. Keep the ones where you actually run workloads.&lt;/li&gt;
&lt;li&gt;Save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvggpjvfsdnaskk1nscm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvggpjvfsdnaskk1nscm.png" alt=" " width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done. Your region dropdown now only shows what matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hide Services
&lt;/h2&gt;

&lt;p&gt;Same place, different setting.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://us-east-1.console.aws.amazon.com/settings/home?region=us-east-1" rel="noopener noreferrer"&gt;Unified Settings → Account settings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;Visible Services&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Deselect the services you don't need. I'd recommend keeping &lt;strong&gt;Billing&lt;/strong&gt; so you can still manage costs.&lt;/li&gt;
&lt;li&gt;Save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85ge6syjpmn6z9twyh2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85ge6syjpmn6z9twyh2u.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens When You Access Something Hidden?
&lt;/h2&gt;

&lt;p&gt;You'll see a page like this if you navigate to a hidden region/service directly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8os34ulrswigxdakdb9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8os34ulrswigxdakdb9t.png" alt=" " width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And some parts of the console will show a restricted indicator:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2r765sixs8odrrkl0yfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2r765sixs8odrrkl0yfz.png" alt=" " width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, nothing is actually blocked. It's just hidden from the default navigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/customize-your-aws-management-console-experience-with-visual-settings-including-account-color-region-and-service-visibility/" rel="noopener noreferrer"&gt;AWS Blog: Customize your console experience&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/03/account-customizations-console/" rel="noopener noreferrer"&gt;What's New: Account customizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/visible-regions-services.html" rel="noopener noreferrer"&gt;Docs: Visible regions and services&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Reading a blog post about blog posts is so meta 😂</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Thu, 09 Apr 2026 12:26:43 +0000</pubDate>
      <link>https://forem.com/hacksore/reading-a-blog-post-about-blog-posts-is-so-meta-16g7</link>
      <guid>https://forem.com/hacksore/reading-a-blog-post-about-blog-posts-is-so-meta-16g7</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc" class="crayons-story__hidden-navigation-link"&gt;Top 7 Featured DEV Posts of the Week&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Beaver-powered databases and ancient AI&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/devteam"&gt;
            &lt;img alt="The DEV Team logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1%2Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/jess" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264%2Fb75f6edf-df7b-406e-a56b-43facafb352c.jpg" alt="jess profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jess" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Jess Lee
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Jess Lee
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3461619" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/jess" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264%2Fb75f6edf-df7b-406e-a56b-43facafb352c.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Jess Lee&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/devteam" class="crayons-story__secondary fw-medium"&gt;The DEV Team&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc" id="article-link-3461619"&gt;
          Top 7 Featured DEV Posts of the Week
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/top7"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;top7&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;61&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/devteam/top-7-featured-dev-posts-of-the-week-4idc#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              12&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎💎</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Sun, 22 Mar 2026 16:52:56 +0000</pubDate>
      <link>https://forem.com/hacksore/-25il</link>
      <guid>https://forem.com/hacksore/-25il</guid>
      <description></description>
    </item>
    <item>
      <title>Every AWS S3 Compatible API Provider EVER</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Sun, 22 Mar 2026 16:46:29 +0000</pubDate>
      <link>https://forem.com/hacksore/every-aws-s3-compatible-api-provider-ever-6fc</link>
      <guid>https://forem.com/hacksore/every-aws-s3-compatible-api-provider-ever-6fc</guid>
      <description>&lt;p&gt;You've probably heard of &lt;a href="https://aws.amazon.com/pm/serv-s3" rel="noopener noreferrer"&gt;AWS Simple Storage Service (Amazon S3)&lt;/a&gt;, which allows you to store objects in buckets.&lt;/p&gt;

&lt;p&gt;The AWS S3 API was the original blob storage interface, and many storage providers and technology companies have reverse-engineered or emulated it to ensure compatibility.&lt;/p&gt;

&lt;p&gt;Some notable examples include services like Cloudflare R2 and Backblaze B2, but there are countless others, as you'll see below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;S3-Compatible Offering&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;&lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;td&gt;&lt;a href="https://developers.cloudflare.com/r2/" rel="noopener noreferrer"&gt;R2&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backblaze&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.backblaze.com/cloud-storage" rel="noopener noreferrer"&gt;B2 Cloud Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wasabi&lt;/td&gt;
&lt;td&gt;&lt;a href="https://wasabi.com/cloud-object-storage" rel="noopener noreferrer"&gt;Hot Cloud Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DigitalOcean&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.digitalocean.com/products/spaces" rel="noopener noreferrer"&gt;Spaces&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Cloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cloud.google.com/storage" rel="noopener noreferrer"&gt;Cloud Storage (XML API)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IBM Cloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.ibm.com/products/cloud-object-storage" rel="noopener noreferrer"&gt;Cloud Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oracle&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.oracle.com/cloud/storage/object-storage/" rel="noopener noreferrer"&gt;OCI Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Akamai&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.akamai.com/products/object-storage" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nebius&lt;/td&gt;
&lt;td&gt;&lt;a href="https://nebius.com/services/storage" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alibaba Cloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.alibabacloud.com/en/product/object-storage-service?_p_lc=1" rel="noopener noreferrer"&gt;Object Storage Service (OSS)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tencent Cloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.tencentcloud.com/products/cos" rel="noopener noreferrer"&gt;Cloud Object Storage (COS)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Huawei Cloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.huaweicloud.com/intl/en-us/product/obs.html" rel="noopener noreferrer"&gt;Object Storage Service (OBS)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vultr&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.vultr.com/products/cloud-storage/object-storage" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaleway&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.scaleway.com/en/object-storage/" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.hetzner.com/storage/object-storage" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OVHcloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://us.ovhcloud.com/public-cloud/object-storage/" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UpCloud&lt;/td&gt;
&lt;td&gt;&lt;a href="https://upcloud.com/global/products/object-storage/" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contabo&lt;/td&gt;
&lt;td&gt;&lt;a href="https://contabo.com/en-us/object-storage/" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exoscale&lt;/td&gt;
&lt;td&gt;&lt;a href="https://community.exoscale.com/product/storage/object-storage/" rel="noopener noreferrer"&gt;Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seagate&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.seagate.com/cloud/object-storage/" rel="noopener noreferrer"&gt;Lyve Cloud Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDrive&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.idrive.com/s3-storage-e2/s3-storage" rel="noopener noreferrer"&gt;e2&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoreWeave&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.coreweave.com/products/storage#object-storage" rel="noopener noreferrer"&gt;AI Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gcore&lt;/td&gt;
&lt;td&gt;&lt;a href="https://gcore.com/storage" rel="noopener noreferrer"&gt;Gcore Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Synology&lt;/td&gt;
&lt;td&gt;&lt;a href="https://c2.synology.com/en-us/object-storage/overview" rel="noopener noreferrer"&gt;C2 Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MEGA&lt;/td&gt;
&lt;td&gt;&lt;a href="https://mega.io/objectstorage" rel="noopener noreferrer"&gt;S4 Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storj&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.storj.io/cloud-object-storage" rel="noopener noreferrer"&gt;Cloud Object Storage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This list is certainly not exhaustive, as there are more services I haven't discovered in my research.&lt;/p&gt;

&lt;p&gt;If I missed any, leave me a comment so I can update the list! Also, don’t be shy and tell me which ones are your favorite to use.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>anyone shipping anything on Sunday?</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Sun, 08 Mar 2026 21:01:16 +0000</pubDate>
      <link>https://forem.com/hacksore/anyone-shipping-anything-on-sunday-36p</link>
      <guid>https://forem.com/hacksore/anyone-shipping-anything-on-sunday-36p</guid>
      <description></description>
    </item>
    <item>
      <title>Neovim Matching Your System Theme 🌚🌞</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Mon, 23 Feb 2026 18:00:00 +0000</pubDate>
      <link>https://forem.com/hacksore/neovim-matching-your-system-theme-ekg</link>
      <guid>https://forem.com/hacksore/neovim-matching-your-system-theme-ekg</guid>
      <description>&lt;p&gt;In this post I'll show you how to get your theme in Neovim to match your system theme.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz2vgyzatwgmsfrc90e4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz2vgyzatwgmsfrc90e4.gif" alt=" " width="720" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First you want to install &lt;a href="https://github.com/cormacrelf/dark-notify/issues" rel="noopener noreferrer"&gt;dark-notify&lt;/a&gt;, here is how you'd do that with Homebrew.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install cormacrelf/tap/dark-notify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can setup the Neovim lazy companion plugin which will watch for changes via the &lt;code&gt;dark-notify&lt;/code&gt; CLI.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;&amp;lt;lightTheme&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;darkTheme&amp;gt;&lt;/code&gt; with your preferred colorschemes (like "catppuccin-latte" and "catppuccin-mocha").&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="c1"&gt;---@module "lazy"&lt;/span&gt;
&lt;span class="c1"&gt;---@type LazySpec&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"cormacrelf/dark-notify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dark_notify"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="n"&gt;schemes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;light&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;colorscheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;lightTheme&amp;gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="n"&gt;dark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;colorscheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;darkTheme&amp;gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to switch your system theme and it will automagically update your Neovim theme.&lt;/p&gt;

&lt;p&gt;You can take a look at &lt;a href="https://github.com/Hacksore/dotfiles/blob/master/.config/nvim/lua/hacksore/plugins/dark-notify.lua" rel="noopener noreferrer"&gt;my Dotfiles&lt;/a&gt; and how I've configured it. If this article helped you out feel free to follow me for more tips and tricks.&lt;/p&gt;

</description>
      <category>neovim</category>
      <category>lua</category>
    </item>
    <item>
      <title>Safari &amp; Firefox extensions still break &lt;pre&gt;/&lt;code&gt; blocks after page load</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Fri, 02 Jan 2026 19:35:11 +0000</pubDate>
      <link>https://forem.com/hacksore/safari-firefox-extensions-still-break-blocks-after-page-load-484a</link>
      <guid>https://forem.com/hacksore/safari-firefox-extensions-still-break-blocks-after-page-load-484a</guid>
      <description></description>
      <category>discuss</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>1Password Breaks Syntax Highlighting On The Internet</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Fri, 02 Jan 2026 18:30:00 +0000</pubDate>
      <link>https://forem.com/hacksore/1password-breaks-syntax-highlighting-on-the-internet-18j6</link>
      <guid>https://forem.com/hacksore/1password-breaks-syntax-highlighting-on-the-internet-18j6</guid>
      <description>&lt;p&gt;&lt;strong&gt;READ FIRST: &lt;a href="https://www.1password.community/discussions/developers/1password-chrome-extension-is-incorrectly-manipulating--blocks/165639/replies/165982" rel="noopener noreferrer"&gt;It has been patched, and the latest official update from the 1Password team&lt;br&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting sometime in early December of 2025, a change was rolled out to the 1Password browser extension that began injecting &lt;a href="https://prismjs.com/" rel="noopener noreferrer"&gt;prism.js&lt;/a&gt; onto every site and targeting every &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; block it encountered.&lt;/p&gt;

&lt;p&gt;The original discovery was made by &lt;a class="mentioned-user" href="https://dev.to/saltyaom"&gt;@saltyaom&lt;/a&gt; and shared on Twitter to their disbelief.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2005701290870087817-127" src="https://platform.twitter.com/embed/Tweet.html?id=2005701290870087817"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2005701290870087817-127');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2005701290870087817&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;The moment it hit my radar was when &lt;a class="mentioned-user" href="https://dev.to/yyx990803"&gt;@yyx990803&lt;/a&gt; retweeted it, amplifying it to a much larger audience.&lt;br&gt;


&lt;iframe class="tweet-embed" id="tweet-2005904473332564339-344" src="https://platform.twitter.com/embed/Tweet.html?id=2005904473332564339"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2005904473332564339-344');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2005904473332564339&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;1Password has several forum posts on this topic showing that this bug was introduced to all production users.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.1password.community/discussions/developers/re-1password-chrome-extension-is-incorrectly-manipulating--blocks/165329" rel="noopener noreferrer"&gt;Re: 1Password Chrome extension is incorrectly manipulating &lt;code&gt; blocks
&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.1password.community/discussions/developers/safari--firefox-extensions-still-break--blocks-after-page-load/166020" rel="noopener noreferrer"&gt;Safari &amp;amp; Firefox extensions still break &amp;lt;pre&amp;gt;/&amp;lt;code&amp;gt; blocks after page load&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.1password.community/discussions/developers/1password-chrome-extension-is-incorrectly-manipulating--blocks/165639" rel="noopener noreferrer"&gt;1Password Chrome extension is incorrectly manipulating &lt;code&gt; blocks
&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest question I had was: why are they even injecting Prism.js in the first place?&lt;/p&gt;

&lt;p&gt;It turns out this is for a new &lt;a href="https://1password.com/blog/product-update-features-and-security-q3-2024" rel="noopener noreferrer"&gt;Labs Snippets feature&lt;/a&gt; that allows you to paste snippets from the browser extension. One of the most interesting parts is that it has nothing to do with programming in general and is instead meant for rich text formatting.&lt;/p&gt;

&lt;p&gt;Prism.js was targeting every &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; block on any site, ultimately stripping the correct syntax highlighting theme.&lt;/p&gt;

&lt;p&gt;The snippets feature itself is actually pretty neat. In this example, it replaces what I type — &lt;code&gt;"sig"&lt;/code&gt; — with &lt;strong&gt;console.log(67)&lt;/strong&gt;. It’s not clear to me why this requires highlighting &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; blocks on websites, though, since this feature behaves more like &lt;a href="https://textexpander.com" rel="noopener noreferrer"&gt;TextExpander&lt;/a&gt; or &lt;a href="https://support.apple.com/guide/mac-help/replace-text-punctuation-documents-mac-mh35735/mac" rel="noopener noreferrer"&gt;macOS text replacements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2007089632660639822-733" src="https://platform.twitter.com/embed/Tweet.html?id=2007089632660639822"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2007089632660639822-733');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2007089632660639822&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;It sucks to have a bug roll out during the holidays when people are on vacation, so I understand the delay in the fix. I’m very excited to read their postmortem to learn how this made it into production and what they plan to do to prevent this from happening again.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this read, and if you’re interested in deep dives like this, please consider following me.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>is the timeline still ai slop or no?</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Sun, 30 Nov 2025 00:01:04 +0000</pubDate>
      <link>https://forem.com/hacksore/is-the-timeline-still-ai-slop-or-no-2215</link>
      <guid>https://forem.com/hacksore/is-the-timeline-still-ai-slop-or-no-2215</guid>
      <description></description>
    </item>
    <item>
      <title>Bitnami MySQL Docker Image Tags Deleted</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Fri, 21 Nov 2025 13:35:36 +0000</pubDate>
      <link>https://forem.com/hacksore/bitnami-mysql-docker-image-tags-deleted-5acm</link>
      <guid>https://forem.com/hacksore/bitnami-mysql-docker-image-tags-deleted-5acm</guid>
      <description>&lt;p&gt;So &lt;a href="https://en.wikipedia.org/wiki/Bitnami" rel="noopener noreferrer"&gt;Bitnami&lt;/a&gt; was &lt;a href="https://www.cloudcomputing-news.net/news/vmware-acquires-bitnami-accelerate-multi-cloud-and-enterprise-deployments/" rel="noopener noreferrer"&gt;acquired by VMware&lt;/a&gt; and they did some business shenanigans and then got rid of all the &lt;a href="https://hub.docker.com/r/bitnami/mysql/tags" rel="noopener noreferrer"&gt;bitnami/mysql&lt;/a&gt; tags.&lt;/p&gt;

&lt;p&gt;Errors you may have encountered when trying to start your db container.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;manifest for bitnami/mysql:latest not found: manifest unknown&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Unable to find image 'bitnami/mysql:latest' locally&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article should give you some options to get a working docker mysql db.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://hub.docker.com/_/mysql" rel="noopener noreferrer"&gt;mysql/mysql&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can use the official mysql docker image but it will require you to change a few things.&lt;/p&gt;

&lt;p&gt;Docker compose file where you can replace the "mydbname" with something more descriptive for you app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mydbname-data:/var/lib/mysql&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3306:3306&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CMD'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mysqladmin'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ping'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-h'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-u'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-pdev'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mydbname-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; file with a DB url.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mysql://root:dev@localhost/mydbname"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://hub.docker.com/r/bitnamisecure/mariadb" rel="noopener noreferrer"&gt;bitnamisecure/mariadb&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The alternative is use the new &lt;code&gt;bitnamisecure/mariadb&lt;/code&gt; but that comes with some risk if they rug pull this image too.&lt;/p&gt;

&lt;p&gt;Docker compose file where you can replace the "mydbname" with something more descriptive for you app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bitnamisecure/mariadb:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname-db&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MARIADB_ROOT_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
      &lt;span class="na"&gt;MARIADB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
      &lt;span class="na"&gt;MARIADB_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CMD'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mysqladmin'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ping'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-h'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;20s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mydbname-data:/bitnami/mysql/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3306:3306&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bitnami/redis:latest'&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydbname-redis&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ALLOW_EMPTY_PASSWORD=yes&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;6379:6379&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mydbname-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; file with a DB url.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mysql://dev:dev@localhost/mydbname"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>database</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Dual publish ESM and CJS with tsdown</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Thu, 04 Sep 2025 13:34:31 +0000</pubDate>
      <link>https://forem.com/hacksore/dual-publish-esm-and-cjs-with-tsdown-2l75</link>
      <guid>https://forem.com/hacksore/dual-publish-esm-and-cjs-with-tsdown-2l75</guid>
      <description>&lt;p&gt;There comes a time when you &lt;em&gt;have to&lt;/em&gt; dual publish ESM (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;ECMAScript&lt;/a&gt;) and CJS (&lt;a href="https://en.wikipedia.org/wiki/CommonJS" rel="noopener noreferrer"&gt;CommonJS&lt;/a&gt;) for your TypeScript projects. This guide should walk you through the steps to get this working properly with &lt;a href="https://tsdown.dev/" rel="noopener noreferrer"&gt;tsdown&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: if you are using &lt;a href="https://tsup.egoist.dev" rel="noopener noreferrer"&gt;tsup&lt;/a&gt; there is a &lt;a href="https://tsdown.dev/guide/migrate-from-tsup" rel="noopener noreferrer"&gt;codemod provided by tsdown to migrate&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  tsdown setup
&lt;/h2&gt;

&lt;p&gt;First let's install &lt;code&gt;tsdown&lt;/code&gt; with your favorite package manager, in this case I'll be using &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm i -D tsdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we can create the &lt;code&gt;tsdown.config.ts&lt;/code&gt; file that will have our configuration.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// NOTE: this is the default but update if your entrypoint differs&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/index.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;sourcemap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  package json setup
&lt;/h2&gt;

&lt;p&gt;It's important to get these right otherwise types will fail to resolve in every scenario.&lt;/p&gt;

&lt;p&gt;Add the following to your &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.cjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"import"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.js"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.d.cts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.cjs"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  validation
&lt;/h2&gt;

&lt;p&gt;We can us the &lt;a href="https://www.npmjs.com/package/@arethetypeswrong/cli" rel="noopener noreferrer"&gt;are the types wrong CLI&lt;/a&gt; to interrogate the output and ensure type resolution is working in all scenarios.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx -y @arethetypeswrong/cli --pack .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Which should yield something like this if all goes well.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; No problems found 🌟


┌───────────────────┬───────────────────────────────┐
│                   │ "tsdown-dual-publish-esm-cjs" │
├───────────────────┼───────────────────────────────┤
│ node10            │ 🟢                            │
├───────────────────┼───────────────────────────────┤
│ node16 (from CJS) │ 🟢 (CJS)                      │
├───────────────────┼───────────────────────────────┤
│ node16 (from ESM) │ 🟢 (ESM)                      │
├───────────────────┼───────────────────────────────┤
│ bundler           │ 🟢                            │
└───────────────────┴───────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Here is a simple demo I've created to show what we've seen here.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Hacksore" rel="noopener noreferrer"&gt;
        Hacksore
      &lt;/a&gt; / &lt;a href="https://github.com/Hacksore/tsdown-dual-publish-esm-cjs" rel="noopener noreferrer"&gt;
        tsdown-dual-publish-esm-cjs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;tsdown-dual-publish-esm-cjs&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;If you want to migrate from &lt;code&gt;tsup&lt;/code&gt; this is a repo to follow.&lt;/p&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;pnpm i
pnpm test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What the ouput of &lt;code&gt;test&lt;/code&gt; looks like.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;&amp;gt; tsdown
ℹ tsdown v0.14.2 powered by rolldown v1.0.0-beta.34
ℹ Using tsdown config: /Users/hacksore/code/tsdown-dual-publish-esm-cjs/tsdown.config.ts
ℹ entry: src/index.ts
ℹ tsconfig: tsconfig.json
ℹ Build start
ℹ Cleaning 4 files
ℹ [CJS] dist/index.cjs  0.10 kB │ gzip: 0.11 kB
ℹ [CJS] 1 files, total: 0.10 kB
ℹ [CJS] dist/index.d.cts  0.09 kB │ gzip: 0.10 kB
ℹ [CJS] 1 files, total: 0.09 kB
ℹ [ESM] dist/index.js    0.10 kB │ gzip: 0.11 kB
ℹ [ESM] dist/index.d.ts  0.09 kB │ gzip: 0.10 kB
ℹ [ESM] 2 files, total: 0.19 kB
✔ Build complete in 575ms

tsdown-dual-publish-esm-cjs v0.0.0

Build tools:
- typescript@~5.8.3
- tsdown@^0.14.2

 No problems found 🌟


┌───────────────────┬───────────────────────────────┐
│                   │ "tsdown-dual-publish-esm-cjs" │
├───────────────────┼───────────────────────────────┤
│ node10            │ 🟢                            │
├───────────────────┼───────────────────────────────┤
│ node16 (from CJS) │ 🟢 (CJS)                      │
├───────────────────┼───────────────────────────────┤
│ node16 (from&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Hacksore/tsdown-dual-publish-esm-cjs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>cjs</category>
    </item>
    <item>
      <title>Vercel Menubar Apps</title>
      <dc:creator>Sean Boult</dc:creator>
      <pubDate>Thu, 21 Aug 2025 17:29:00 +0000</pubDate>
      <link>https://forem.com/hacksore/vercel-menubar-apps-3i96</link>
      <guid>https://forem.com/hacksore/vercel-menubar-apps-3i96</guid>
      <description>&lt;p&gt;Just a few toolbar apps people have built for &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;vercel.com&lt;/a&gt; to track your deployments.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://trydeplog.com" rel="noopener noreferrer"&gt;deplog&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Monitor your Vercel deployments real-time on your Mac—no need to open the web app! With Deplog, all your deployment updates are just one click away, right from your Mac’s menu bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5y18es8u6kd9uw0li9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5y18es8u6kd9uw0li9j.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Credit: &lt;a href="https://x.com/emredemirbulut" rel="noopener noreferrer"&gt;@emredemirbulut&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/rajatkulkarni95/buildlog" rel="noopener noreferrer"&gt;buildlog&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Vercel Deployments in Menu Bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2t2oxpi62uha5d9bazl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2t2oxpi62uha5d9bazl.png" alt=" " width="800" height="789"&gt;&lt;/a&gt;&lt;br&gt;
Credit: &lt;a href="https://x.com/@JokingRajat" rel="noopener noreferrer"&gt;@JokingRajat&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://github.com/R44VC0RP/vercel-toolbar" rel="noopener noreferrer"&gt;vercel-toolbar&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A sleek macOS menu bar application for viewing your Vercel deployments in real-time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwz6gq02v2geb9edzdig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwz6gq02v2geb9edzdig.png" alt=" " width="800" height="893"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Credit: &lt;a href="https://x.com/ryandavogel" rel="noopener noreferrer"&gt;@ryandavogel&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Very cool projects from these folks and one day maybe vercel will ship a 1st party one!&lt;/p&gt;

&lt;p&gt;If you made it this far you can also see what I wanted to build for github called &lt;a href="https://buildtray.com" rel="noopener noreferrer"&gt;buildtray.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vercel</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
