<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Brian Ruiz</title>
        <link>https://b-r.io</link>
        <description>Writing about software engineering, technology, design, and productivity.</description>
        <lastBuildDate>Tue, 21 Jul 2026 08:41:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Brian Ruiz</title>
            <url>https://b-r.io/favicon.ico</url>
            <link>https://b-r.io</link>
        </image>
        <copyright>All rights reserved 2026</copyright>
        <item>
            <title><![CDATA[Add beautiful maps to your React app with Mapbox GL]]></title>
            <link>https://b-r.io/posts/add-beautiful-maps-to-your-react-app-with-mapbox-gl</link>
            <guid isPermaLink="false">https://b-r.io/posts/add-beautiful-maps-to-your-react-app-with-mapbox-gl</guid>
            <pubDate>Sat, 27 Apr 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<figure><div class="not-prose relative overflow-hidden rounded-3xl bg-muted" style="height:400px"><div class="map-container h-full w-full"></div><div class="pointer-events-none absolute bottom-4 left-4 z-10 flex flex-col rounded-lg border bg-background px-4 py-2 leading-none md:bottom-6 md:left-6"><p class="m-0 text-sm text-muted-foreground">Location</p><p class="m-0 text-lg font-semibold text-foreground">New York, NY</p></div></div><figcaption><p>The Met on the edge of Central Park at dusk. Mapbox Standard's dusk
preset is rich in detail. This is what we will build: camera, lighting, badge,
then marker.</p></figcaption></figure>
<p>I recently had to add a map to a React app and was not sure what to reach for. After some research I landed on <a href="https://docs.mapbox.com/mapbox-gl-js/api/">Mapbox GL JS</a>, and it turned out to be both easier and more capable than I expected.</p>
<p>The map above is the finished piece. Below we build it in order: create the component, configure the camera and padding, pick a lighting theme, then drop in a marker. Play with it first: zoom, <code>ctrl + drag</code> for pitch and rotation, or <code>shift + drag</code> to scale.</p>
<h2>Getting Started</h2>
<p>You need a Mapbox account and an access token. Sign up at <a href="https://account.mapbox.com/">Mapbox Account</a> and grab the token from the account home page. The free tier includes 50,000 map loads a month, which is plenty for most side projects.</p>
<p>Install the library, then set the token. In Next.js that means a <code>NEXT_PUBLIC_</code> env var so it is available in the browser:</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1"><span class="token string">'use client'</span>
</span><span class="code-line line-number" line="2">
</span><span class="code-line line-number" line="3"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useRef<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">'react'</span>
</span><span class="code-line line-number" line="4"><span class="token keyword module">import</span> <span class="token imports">mapboxgl</span> <span class="token keyword module">from</span> <span class="token string">'mapbox-gl'</span>
</span><span class="code-line line-number" line="5"><span class="token keyword module">import</span> <span class="token string">'mapbox-gl/dist/mapbox-gl.css'</span>
</span><span class="code-line line-number" line="6"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useTheme <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">'next-themes'</span>
</span><span class="code-line line-number" line="7">
</span><span class="code-line line-number" line="8">mapboxgl<span class="token punctuation">.</span><span class="token property-access">accessToken</span> <span class="token operator">=</span> process<span class="token punctuation">.</span><span class="token property-access">env</span><span class="token punctuation">.</span><span class="token constant">NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN</span>
</span></code></pre>
<h2>Creating the Map Component</h2>
<p>Two refs keep things stable across renders: one for the DOM container, and one for the Mapbox instance so we do not recreate it on every update. Props like <code>lng</code>, <code>lat</code>, <code>zoom</code>, and <code>pitch</code> point the camera. Full options live in the <a href="https://docs.mapbox.com/mapbox-gl-js/api/map/">Map API reference</a>.</p>
<p>Initialize once inside <code>useEffect</code>. If <code>map.current</code> already exists, bail early.</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1"><span class="token keyword module">export</span> <span class="token keyword module">default</span> <span class="token keyword">function</span> <span class="token known-class-name class-name">Map</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> lng<span class="token punctuation">,</span> lat<span class="token punctuation">,</span> zoom <span class="token operator">=</span> <span class="token number">2.5</span><span class="token punctuation">,</span> pitch <span class="token operator">=</span> <span class="token number">25</span> <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="2">  <span class="token keyword">const</span> mapContainer <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword null nil">null</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="3">  <span class="token keyword">const</span> map <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword null nil">null</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="4">
</span><span class="code-line line-number highlight-line" line="5">  <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number highlight-line" line="6">    <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">)</span> <span class="token keyword control-flow">return</span>
</span><span class="code-line line-number highlight-line" line="7">    map<span class="token punctuation">.</span><span class="token property-access">current</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">mapboxgl<span class="token punctuation">.</span>Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line line-number highlight-line" line="8">      <span class="token literal-property property">container</span><span class="token operator">:</span> mapContainer<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="9">      <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">'mapbox://styles/mapbox/standard'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="10">      <span class="token literal-property property">center</span><span class="token operator">:</span> <span class="token punctuation">[</span>lng<span class="token punctuation">,</span> lat<span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="11">      zoom<span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="12">      pitch<span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="13">    <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="14">    <span class="token comment">// ...</span>
</span><span class="code-line line-number" line="15">  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="16">
</span><span class="code-line line-number" line="17">  <span class="token keyword control-flow">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">ref</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>mapContainer<span class="token punctuation">}</span></span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>map-container h-full w-full<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</span><span class="code-line line-number" line="18"><span class="token punctuation">}</span>
</span></code></pre>
<h2>Configuring the Map</h2>
<p>Once the style loads, set the basemap lighting and a little left padding. Padding makes room for a location badge and keeps the pin from sitting under the overlay on wide layouts.</p>
<p>For the cover demo, the camera points at The Met on the edge of Central Park:</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1"><span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="2">  <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">)</span> <span class="token keyword control-flow">return</span>
</span><span class="code-line line-number" line="3">  map<span class="token punctuation">.</span><span class="token property-access">current</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">mapboxgl<span class="token punctuation">.</span>Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line line-number" line="4">    <span class="token literal-property property">container</span><span class="token operator">:</span> mapContainer<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="5">    <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">'mapbox://styles/mapbox/standard'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="6">    <span class="token literal-property property">center</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">73.963244</span><span class="token punctuation">,</span> <span class="token number">40.779437</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// The Met, NYC</span>
</span><span class="code-line line-number highlight-line" line="7">    <span class="token literal-property property">zoom</span><span class="token operator">:</span> <span class="token number">15.5</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="8">    <span class="token literal-property property">pitch</span><span class="token operator">:</span> <span class="token number">45</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="9">  <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="10">
</span><span class="code-line line-number" line="11">  map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">'style.load'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number highlight-line" line="12">    map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setConfigProperty</span><span class="token punctuation">(</span><span class="token string">'basemap'</span><span class="token punctuation">,</span> <span class="token string">'lightPreset'</span><span class="token punctuation">,</span> mapTheme<span class="token punctuation">)</span>
</span><span class="code-line line-number highlight-line" line="13">    map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setPadding</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">left</span><span class="token operator">:</span> <span class="token number">150</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="14">    <span class="token comment">// ...</span>
</span><span class="code-line line-number" line="15">  <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="16"><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span></code></pre>
<p>The badge itself is just absolute-positioned JSX on top of the map. You do not need to register it with Mapbox:</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>relative<span class="token punctuation">"</span></span> <span class="token attr-name">style</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token literal-property property">height</span><span class="token operator">:</span> <span class="token number">400</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">  </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Map</span></span> <span class="token attr-name">lng</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token operator">-</span><span class="token number">73.963244</span><span class="token punctuation">}</span></span> <span class="token attr-name">lat</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token number">40.779437</span><span class="token punctuation">}</span></span> <span class="token attr-name">zoom</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token number">15.5</span><span class="token punctuation">}</span></span> <span class="token attr-name">pitch</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token number">45</span><span class="token punctuation">}</span></span> <span class="token punctuation">/&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text">  </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">MapLocationBadge</span></span> <span class="token attr-name">place</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>New York, NY<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line"><span class="token plain-text"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</span></code></pre>
<div class="not-prose relative my-8 overflow-hidden rounded-3xl bg-muted" style="height:300px"><div class="pointer-events-none absolute bottom-4 left-4 z-10 flex flex-col rounded-lg border bg-background px-4 py-2 leading-none md:bottom-6 md:left-6"><p class="m-0 text-sm text-muted-foreground">Location</p><p class="m-0 text-lg font-semibold text-foreground">New York, NY</p></div></div>
<h2>Applying Themes</h2>
<p>Mapbox Standard ships four light presets: <code>day</code>, <code>night</code>, <code>dusk</code>, and <code>dawn</code>. That <code>lightPreset</code> call above is where you pick one.</p>
<p>I sync the map with the rest of the site using <code>next-themes</code>, so it follows light and dark mode automatically. You can also hardcode <code>dusk</code> when you want a specific mood, like the Met cover at the top of this post. If the theme can change while the map is mounted, update <code>lightPreset</code> again whenever <code>resolvedTheme</code> changes.</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1"><span class="token keyword">const</span> <span class="token punctuation">{</span> resolvedTheme <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useTheme</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="2"><span class="token keyword">const</span> mapTheme <span class="token operator">=</span> resolvedTheme <span class="token operator">===</span> <span class="token string">'dark'</span> <span class="token operator">?</span> <span class="token string">'night'</span> <span class="token operator">:</span> <span class="token string">'day'</span>
</span></code></pre>
<div class="not-prose grid grid-cols-2 gap-3"><div class="overflow-hidden rounded-3xl bg-muted"><img alt="One World Trade Center on a light Mapbox theme" loading="lazy" width="320" height="320" decoding="async" data-nimg="1" class="h-auto w-full" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-light.12caruet57~61.png&amp;w=384&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-light.12caruet57~61.png&amp;w=640&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-light.12caruet57~61.png&amp;w=640&amp;q=75"></div><div class="overflow-hidden rounded-3xl bg-muted"><img alt="One World Trade Center on a dark Mapbox theme" loading="lazy" width="320" height="320" decoding="async" data-nimg="1" class="h-auto w-full" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-dark.0c5i~62y0mtqd.png&amp;w=384&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-dark.0c5i~62y0mtqd.png&amp;w=640&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnyc-dark.0c5i~62y0mtqd.png&amp;w=640&amp;q=75"></div></div>
<figcaption><p>One World Trade Center in New York City. Day is clean and easy to read, great
when the map is mostly functional. Night is where Standard gets fun: building
windows light up and 3D landmarks pick up a warm glow that feels almost
cinematic. Dusk and dawn sit in between if you want atmosphere without going
full night.</p></figcaption>
<h2>Adding a Marker</h2>
<p>Finally, add a marker for the point of interest. It can be any HTML element. A small span with a CSS class is enough, and you can style it however you like.</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1">map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">'style.load'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="2">  map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setConfigProperty</span><span class="token punctuation">(</span><span class="token string">'basemap'</span><span class="token punctuation">,</span> <span class="token string">'lightPreset'</span><span class="token punctuation">,</span> mapTheme<span class="token punctuation">)</span>
</span><span class="code-line line-number" line="3">  map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setPadding</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">left</span><span class="token operator">:</span> <span class="token number">150</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="4">
</span><span class="code-line line-number highlight-line" line="5">  <span class="token keyword">const</span> el <span class="token operator">=</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token method function property-access">createElement</span><span class="token punctuation">(</span><span class="token string">'span'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number highlight-line" line="6">  el<span class="token punctuation">.</span><span class="token property-access">className</span> <span class="token operator">=</span> <span class="token string">'map-marker'</span>
</span><span class="code-line line-number highlight-line" line="7">  <span class="token keyword">new</span> <span class="token class-name">mapboxgl<span class="token punctuation">.</span>Marker</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">element</span><span class="token operator">:</span> el<span class="token punctuation">,</span> <span class="token literal-property property">anchor</span><span class="token operator">:</span> <span class="token string">'center'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number highlight-line" line="8">    <span class="token punctuation">.</span><span class="token method function property-access">setLngLat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">73.963244</span><span class="token punctuation">,</span> <span class="token number">40.779437</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="9">    <span class="token punctuation">.</span><span class="token method function property-access">addTo</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="10"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre>
<pre class="language-css"><span class="code-block-label font-sans text-sm font-semibold text-white/90">CSS</span><code class="language-css code-highlight"><span class="code-line line-number" line="1"><span class="token selector"><span class="token class">.map-marker</span></span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="2">  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">24</span><span class="token unit">px</span><span class="token punctuation">;</span>
</span><span class="code-line line-number" line="3">  <span class="token property">height</span><span class="token punctuation">:</span> <span class="token number">24</span><span class="token unit">px</span><span class="token punctuation">;</span>
</span><span class="code-line line-number" line="4">  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token number">50</span><span class="token unit">%</span><span class="token punctuation">;</span>
</span><span class="code-line line-number" line="5">  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span><span class="token variable">--accent</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class="code-line line-number" line="6">  <span class="token property">border</span><span class="token punctuation">:</span> <span class="token number">3</span><span class="token unit">px</span> solid <span class="token color"><span class="token function">rgba</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0.95</span><span class="token punctuation">)</span></span><span class="token punctuation">;</span>
</span><span class="code-line line-number" line="7"><span class="token punctuation">}</span>
</span></code></pre>
<p>Do not set <code>transform</code> on the marker element. Mapbox uses it for positioning, and a custom transform will throw the pin off the building.</p>
<div class="not-prose relative my-8 overflow-hidden rounded-3xl bg-muted" style="height:300px"><div class="pointer-events-none absolute bottom-4 left-4 z-10 flex flex-col rounded-lg border bg-background px-4 py-2 leading-none md:bottom-6 md:left-6"><p class="m-0 text-sm text-muted-foreground">Location</p><p class="m-0 text-lg font-semibold text-foreground">New York, NY</p></div><span class="absolute z-10 size-6 rounded-full border-[3px] border-white bg-accent shadow" style="bottom:50%;right:33%"></span></div>
<h2>Conclusion</h2>
<p>Remember <code>ref={mapContainer}</code> on the div Mapbox should render into. Putting it all together:</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line line-number" line="1"><span class="token string">'use client'</span>
</span><span class="code-line line-number" line="2">
</span><span class="code-line line-number" line="3"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useEffect<span class="token punctuation">,</span> useRef <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">'react'</span>
</span><span class="code-line line-number" line="4"><span class="token keyword module">import</span> <span class="token imports">mapboxgl</span> <span class="token keyword module">from</span> <span class="token string">'mapbox-gl'</span>
</span><span class="code-line line-number" line="5"><span class="token keyword module">import</span> <span class="token string">'mapbox-gl/dist/mapbox-gl.css'</span>
</span><span class="code-line line-number" line="6"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useTheme <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">'next-themes'</span>
</span><span class="code-line line-number" line="7">
</span><span class="code-line line-number" line="8">mapboxgl<span class="token punctuation">.</span><span class="token property-access">accessToken</span> <span class="token operator">=</span> process<span class="token punctuation">.</span><span class="token property-access">env</span><span class="token punctuation">.</span><span class="token constant">NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN</span>
</span><span class="code-line line-number" line="9">
</span><span class="code-line line-number" line="10"><span class="token keyword module">export</span> <span class="token keyword module">default</span> <span class="token keyword">function</span> <span class="token known-class-name class-name">Map</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
</span></span><span class="code-line line-number" line="11"><span class="token parameter">  lng <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">73.963244</span><span class="token punctuation">,</span>
</span></span><span class="code-line line-number" line="12"><span class="token parameter">  lat <span class="token operator">=</span> <span class="token number">40.779437</span><span class="token punctuation">,</span>
</span></span><span class="code-line line-number" line="13"><span class="token parameter">  zoom <span class="token operator">=</span> <span class="token number">15.5</span><span class="token punctuation">,</span>
</span></span><span class="code-line line-number" line="14"><span class="token parameter">  pitch <span class="token operator">=</span> <span class="token number">45</span><span class="token punctuation">,</span>
</span></span><span class="code-line line-number" line="15"><span class="token parameter"><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="16">  <span class="token keyword">const</span> mapContainer <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword null nil">null</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="17">  <span class="token keyword">const</span> map <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword null nil">null</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="18">
</span><span class="code-line line-number" line="19">  <span class="token keyword">const</span> <span class="token punctuation">{</span> resolvedTheme <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useTheme</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="20">  <span class="token keyword">const</span> mapTheme <span class="token operator">=</span> resolvedTheme <span class="token operator">===</span> <span class="token string">'dark'</span> <span class="token operator">?</span> <span class="token string">'night'</span> <span class="token operator">:</span> <span class="token string">'day'</span>
</span><span class="code-line line-number" line="21">
</span><span class="code-line line-number" line="22">  <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="23">    <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token property-access">current</span> <span class="token operator">||</span> <span class="token operator">!</span>mapContainer<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">)</span> <span class="token keyword control-flow">return</span>
</span><span class="code-line line-number" line="24">
</span><span class="code-line line-number" line="25">    map<span class="token punctuation">.</span><span class="token property-access">current</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">mapboxgl<span class="token punctuation">.</span>Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line line-number" line="26">      <span class="token literal-property property">container</span><span class="token operator">:</span> mapContainer<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="27">      <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">'mapbox://styles/mapbox/standard'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="28">      <span class="token literal-property property">center</span><span class="token operator">:</span> <span class="token punctuation">[</span>lng<span class="token punctuation">,</span> lat<span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="29">      zoom<span class="token punctuation">,</span>
</span><span class="code-line line-number" line="30">      pitch<span class="token punctuation">,</span>
</span><span class="code-line line-number" line="31">      <span class="token literal-property property">config</span><span class="token operator">:</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="32">        <span class="token literal-property property">basemap</span><span class="token operator">:</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="33">          <span class="token literal-property property">lightPreset</span><span class="token operator">:</span> mapTheme<span class="token punctuation">,</span>
</span><span class="code-line line-number" line="34">        <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="35">      <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="36">    <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="37">
</span><span class="code-line line-number" line="38">    map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">'style.load'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="39">      map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setConfigProperty</span><span class="token punctuation">(</span><span class="token string">'basemap'</span><span class="token punctuation">,</span> <span class="token string">'lightPreset'</span><span class="token punctuation">,</span> mapTheme<span class="token punctuation">)</span>
</span><span class="code-line line-number" line="40">      map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">setPadding</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">left</span><span class="token operator">:</span> <span class="token number">150</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="41">
</span><span class="code-line line-number" line="42">      <span class="token keyword">const</span> el <span class="token operator">=</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token method function property-access">createElement</span><span class="token punctuation">(</span><span class="token string">'span'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="43">      el<span class="token punctuation">.</span><span class="token property-access">className</span> <span class="token operator">=</span> <span class="token string">'map-marker'</span>
</span><span class="code-line line-number" line="44">      <span class="token keyword">new</span> <span class="token class-name">mapboxgl<span class="token punctuation">.</span>Marker</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">element</span><span class="token operator">:</span> el<span class="token punctuation">,</span> <span class="token literal-property property">anchor</span><span class="token operator">:</span> <span class="token string">'center'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="45">        <span class="token punctuation">.</span><span class="token method function property-access">setLngLat</span><span class="token punctuation">(</span><span class="token punctuation">[</span>lng<span class="token punctuation">,</span> lat<span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="46">        <span class="token punctuation">.</span><span class="token method function property-access">addTo</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="47">    <span class="token punctuation">}</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="48">
</span><span class="code-line line-number" line="49">    <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="50">      map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token operator">?.</span><span class="token method function property-access">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="51">      map<span class="token punctuation">.</span><span class="token property-access">current</span> <span class="token operator">=</span> <span class="token keyword null nil">null</span>
</span><span class="code-line line-number" line="52">    <span class="token punctuation">}</span>
</span><span class="code-line line-number" line="53">  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="54">
</span><span class="code-line line-number" line="55">  <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span>
</span><span class="code-line line-number" line="56">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span>
</span></span><span class="code-line line-number" line="57"><span class="token tag">      <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>relative overflow-hidden rounded-3xl border border-border bg-muted<span class="token punctuation">"</span></span>
</span></span><span class="code-line line-number" line="58"><span class="token tag">      <span class="token attr-name">style</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token literal-property property">height</span><span class="token operator">:</span> <span class="token number">400</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
</span></span><span class="code-line line-number" line="59"><span class="token tag">    <span class="token punctuation">&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line line-number" line="60"><span class="token plain-text">      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">ref</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>mapContainer<span class="token punctuation">}</span></span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>map-container h-full w-full<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span><span class="token plain-text">
</span></span><span class="code-line line-number" line="61"><span class="token plain-text">    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</span><span class="code-line line-number" line="62">  <span class="token punctuation">)</span>
</span><span class="code-line line-number" line="63"><span class="token punctuation">}</span>
</span></code></pre>
<figcaption>Final Map component with The Met as the default camera.</figcaption>
<p>Want the cover-style flyover? After <code>style.load</code>, ease the camera in:</p>
<pre class="language-jsx"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-jsx code-highlight"><span class="code-line">map<span class="token punctuation">.</span><span class="token property-access">current</span><span class="token punctuation">.</span><span class="token method function property-access">easeTo</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token literal-property property">zoom</span><span class="token operator">:</span> <span class="token number">15.5</span><span class="token punctuation">,</span>
</span><span class="code-line">  <span class="token literal-property property">pitch</span><span class="token operator">:</span> <span class="token number">45</span><span class="token punctuation">,</span>
</span><span class="code-line">  <span class="token literal-property property">bearing</span><span class="token operator">:</span> <span class="token operator">-</span><span class="token number">28</span><span class="token punctuation">,</span>
</span><span class="code-line">  <span class="token literal-property property">duration</span><span class="token operator">:</span> <span class="token number">3200</span><span class="token punctuation">,</span>
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre>
<p>Start a little wider and flatter, then ease into those values. No extra animation library required. From there you have an interactive Standard map you can theme, annotate, and drop pins on.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Day in the Life with Invisible Smart Glasses]]></title>
            <link>https://b-r.io/posts/day-in-the-life-with-invisible-smart-glasses</link>
            <guid isPermaLink="false">https://b-r.io/posts/day-in-the-life-with-invisible-smart-glasses</guid>
            <pubDate>Thu, 12 Feb 2026 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p><a href="https://evenrealities.com/">Even Realities</a> reached out and asked if I wanted to try their latest smart glasses. I'm already drawn to wearables and everyday tech, and with so much recent attention on optical devices (Vision Pro, Meta's glasses, and the rest) I couldn't pass it up. This is a day wearing them while commuting, working, and moving through the city, without the usual gadget theater. Here's what I found!</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Software Engineer's Productive and Minimal Desk Setup]]></title>
            <link>https://b-r.io/posts/desk-setup</link>
            <guid isPermaLink="false">https://b-r.io/posts/desk-setup</guid>
            <pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>This post is the companion guide to the video, with all of the links and resources in one place.</p>
<p>I'm a software engineer by day and a part-time creator in the evenings. I spend a lot of hours at this desk coding, editing, and learning, so I put together a setup that stays productive for both.</p>
<h2>The desk</h2>
<p>The centerpiece is the <a href="https://shrsl.com/49346">Ergonofis Sway Desk</a>. It has a slick control interface, an anti-collision system, and the kind of build quality that makes standing all day feel natural. They also sent their solid wood monitor riser / desk shelf, which keeps the display at eye level and adds a bit of structure to the surface.</p>
<ul>
<li><a href="https://shrsl.com/49346">Ergonofis Sway Desk</a>: standing desk with intuitive preset heights</li>
<li><a href="https://shrsl.com/49342">Ergonofis Desk Shelf</a>: solid wood shelf for posture and organization</li>
<li><a href="https://shrsl.com/4933x">Ergonofis Cable Management</a>: keeps the underside tidy</li>
</ul>
<h2>Monitors and lighting</h2>
<p>A good monitor is non-negotiable for my work. I use the LG 34WN780 for its ergonomic stand and wide canvas, plus a BenQ ScreenBar Halo for consistent, glare-free light.</p>
<ul>
<li><a href="https://amzn.to/3DJd86G">LG 34WN780 Monitor</a></li>
<li><a href="https://amzn.to/3fUAfCi">BenQ ScreenBar Halo</a></li>
</ul>
<h2>Computer setup</h2>
<p>My daily driver is a 16-inch MacBook Pro. An Anker USB-C hub cuts down cable clutter, and a Nomad MagSafe dock keeps the phone out of the way.</p>
<ul>
<li><a href="https://amzn.to/41fkhEH">16-inch MacBook Pro</a></li>
<li><a href="https://amzn.to/3Dk9vCV">Anker USB-C Hub</a></li>
<li><a href="https://nomadgoods.com/products/stand-one-silver">Nomad MagSafe Dock</a></li>
</ul>
<h2>Audio</h2>
<p>I mostly work in headphones because monitor speakers aren't enough for editing or focus sessions.</p>
<ul>
<li><a href="https://amzn.to/3mie64b">AirPods Max</a></li>
<li><a href="https://amzn.to/3UmMQhq">Apple AirPods Pro</a></li>
<li><a href="https://amzn.to/46h5E6H">Sonos Beam Soundbar</a></li>
</ul>
<h2>Peripherals</h2>
<p>I'm a mechanical keyboard person. The Mode Envoy with Alexotos linear switches and a GMK Dracula set is still my favorite daily typer. For pointing, I switch between a Logitech MX Master III and an Apple Magic Trackpad.</p>
<ul>
<li><a href="https://amzn.to/3Dm37eu">Orbitkey Desk Mat</a></li>
<li><a href="https://modedesigns.com/pages/envoy">Mode Envoy Keyboard</a></li>
<li><a href="https://modedesigns.com/products/alexotos-edition-switches">Alexotos Linear Switches</a></li>
<li><a href="https://geekhack.org/">GMK Dracula Keycap Set</a></li>
<li><a href="https://amzn.to/3U5syHG">Logitech MX Master III</a></li>
<li><a href="https://amzn.to/46gxWyf">Magic Trackpad</a></li>
</ul>
<h2>Chair and ergonomics</h2>
<p>Long sessions need a chair that stays out of the way. The Herman Miller Aeron covers that with full adjustability and solid lumbar support.</p>
<ul>
<li><a href="https://www.hermanmiller.com">Herman Miller Aeron Chair</a></li>
</ul>
<h2>Miscellaneous</h2>
<ul>
<li><a href="https://www.ikea.com/us/en/p/skadis-pegboard-white-10321618/">Ikea Skådis Pegboard</a></li>
<li><a href="https://amzn.to/46m0CA">Govee RGB Floor Lamp</a></li>
<li><a href="https://amzn.to/46CdXK8">Fellow Products Coffee Grinder</a></li>
<li><a href="https://amzn.to/46fGa9M">Electric Kettle</a></li>
<li><a href="https://amzn.to/48HyP4v">Larq Water Bottle</a></li>
</ul>
<h2>Closing</h2>
<p>That's the workspace as of this write-up. It keeps evolving — if you have suggestions for what to improve around the edges of the desk, I'm always open to them.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Building a Medium-inspired blog with Gatsby.js]]></title>
            <link>https://b-r.io/posts/gatsby-js-medium-blog-starter</link>
            <guid isPermaLink="false">https://b-r.io/posts/gatsby-js-medium-blog-starter</guid>
            <pubDate>Tue, 15 Nov 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>I spend a lot of time reading on Medium, and I always liked how little the interface got in the way. When I needed a personal blog and portfolio of my own, I did not want another generic theme that looked like every other developer site. I wanted something closer to that quieter reading experience, built on tools I already knew.</p>
<p>That led to a <a href="https://gatsby-medium.vercel.app">Gatsby.js starter</a> inspired by Medium’s earlier design. Clean typography, a focused post layout, and enough structure underneath to run a full site: posts, a contact page, gear links, search, and dark mode.</p>
<h2>Features</h2>
<p>Out of the box it includes:</p>
<ul>
<li>📲 PWA support so it can be installed on Android and iOS</li>
<li>🔎 Algolia search across post attributes</li>
<li>📧 A Getform.io contact form that is simple to wire up</li>
<li>📝 MDX-based blog posts</li>
<li>🌗 A theme toggle for light and dark mode</li>
<li>💻 SEO-friendly meta descriptions</li>
</ul>
<p>The stack is Gatsby, React, MUI, MDX, and Vercel.</p>
<figure><img alt="Mobile views of the Gatsby Medium blog starter" loading="lazy" width="1531" height="1021" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.100z91hu8j8ob.png&amp;w=1920&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.100z91hu8j8ob.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.100z91hu8j8ob.png&amp;w=3840&amp;q=75"><figcaption><p>Mobile view, featuring a blog post detail page, the post list, a contact
form, and a gear page with affiliate links.</p></figcaption></figure>
<h2>Writing in MDX</h2>
<p>Publishing is meant to stay out of your way. Day to day you write markdown (or MDX) in <code>content/posts/</code> and the site picks it up. You do not need to touch HTML or CSS for a normal post, though you still can if you want to change the design or drop in custom React components.</p>
<figure><img alt="Tablet view of a responsive blog post layout" loading="lazy" width="1134" height="640" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.00-ydbyuvxk38.png&amp;w=1200&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.00-ydbyuvxk38.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.00-ydbyuvxk38.png&amp;w=3840&amp;q=75"><figcaption><p>Blog posts adapt to the screen. On larger viewports, sidebars for navigation
and metadata come back into view.</p></figcaption></figure>
<h2>Light and dark mode</h2>
<p>There is a toggle in the header for switching themes. Your choice is stored in local storage so it sticks between visits, or you can leave it following the system preference.</p>
<div class="not-prose my-8"><div class="relative md:-mx-12 md:px-12"><div class="overflow-hidden rounded-3xl bg-muted"><div class="flex cursor-grab active:cursor-grabbing"><div class="shrink-0 grow-0" style="width:100%"><img alt="Gatsby Medium blog starter in dark mode on a desktop display" draggable="false" width="2706" height="1623" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdark-computer.01whq78alaous.png&amp;w=3840&amp;q=75"></div><div class="shrink-0 grow-0" style="width:100%"><img alt="Gatsby Medium blog starter in light mode on a desktop display" draggable="false" loading="lazy" width="2706" height="1623" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flight-computer.103ka~jdcx3~y.png&amp;w=3840&amp;q=75"></div></div></div><button type="button" aria-label="Previous image" disabled="" class="absolute top-1/2 z-10 hidden size-9 -translate-y-1/2 items-center justify-center rounded-full bg-card text-foreground shadow-md ring-1 shadow-foreground/5 ring-border transition hover:bg-muted disabled:pointer-events-none disabled:opacity-30 md:flex dark:bg-muted dark:hover:bg-muted/80 left-0"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"></path></svg></button><button type="button" aria-label="Next image" class="absolute top-1/2 z-10 hidden size-9 -translate-y-1/2 items-center justify-center rounded-full bg-card text-foreground shadow-md ring-1 shadow-foreground/5 ring-border transition hover:bg-muted disabled:pointer-events-none disabled:opacity-30 md:flex dark:bg-muted dark:hover:bg-muted/80 right-0"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"></path></svg></button></div><figcaption class="mt-4 text-sm leading-6 text-pretty text-muted-foreground/75">Desktop view of the starter in dark mode and light mode.</figcaption><div class="mt-4 flex items-center justify-center gap-1"><button type="button" aria-label="Image 1 of 2" aria-current="true" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground"></span></button><button type="button" aria-label="Image 2 of 2" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground/20 group-hover:bg-foreground/45"></span></button><span class="sr-only">Image <!-- -->1<!-- --> of <!-- -->2</span></div></div>
<h2>Try the demo</h2>
<p>You can see the live site at <a href="https://gatsby-medium.vercel.app">gatsby-medium.vercel.app</a>. If you want a Medium-like reading experience on Gatsby without starting from a blank theme, this should get you most of the way there.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Getting My Life Together as a Software Engineer]]></title>
            <link>https://b-r.io/posts/getting-my-life-together-as-a-software-engineer</link>
            <guid isPermaLink="false">https://b-r.io/posts/getting-my-life-together-as-a-software-engineer</guid>
            <pubDate>Wed, 01 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>We're back — here's a laid-back look at life lately. Getting back into a productive routine is really important to me, especially when a day job, side projects, and YouTube all start competing for the same hours. Gym, coffee, coding sessions, unboxing the new iPhone 17 Pro, exploring Central Park, and a few small updates along the way.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[How I built a COVID-19 tracking dashboard with Python]]></title>
            <link>https://b-r.io/posts/how-to-create-a-covid-19-dashboard-with-python</link>
            <guid isPermaLink="false">https://b-r.io/posts/how-to-create-a-covid-19-dashboard-with-python</guid>
            <pubDate>Wed, 01 Sep 2021 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<h2>Why start this project?</h2>
<p>When I started this side project there weren't many dashboards or sites to track data for the Coronavirus pandemic, other than the very popular web app created by Johns Hopkins University. My idea was to create an open-source version that encouraged collaboration to derive some creative design and functional ideas. And that's precisely what this project became.</p>
<blockquote>
<p>The best way to prevent and slow down transmission is to be well-informed.
— World Health Organization</p>
</blockquote>
<p>We have <a href="https://github.com/BrianRuizy/covid19-dashboard/graphs/contributors">contributors</a> from all over the world (Spain, Poland, India, and various places in the USA) who came together to create something useful and meaningful. The dashboard ended up receiving over <code>200k</code> visitors, but the most rewarding part was collaborating with people across the world. It brought key stats, cumulative and daily growth charts, country-level tables, and a fully interactive Mapbox map into one responsive overview of the pandemic.</p>
<h2>Data Sources</h2>
<p>A large portion of the data comes from one of the original data repositories tracking COVID-19 cases, <a href="https://github.com/CSSEGISandData/COVID-19">Johns Hopkins University</a> CSSE2019-ncov data repository. Additional data was collected from <a href="https://ourworldindata.org/">Our World in Data</a> GitHub data repository. Lastly, to fill in some requirements we retrieved data for daily cases from <a href="https://github.com/nytimes/covid-19-data">New York Times</a> COVID GitHub data repository.</p>
<p>For this project, it was crucial to have accurate, trustworthy datasets. That is why those sources were carefully chosen. The goal was to represent the pandemic as accurately as possible. Getting that wrong at scale would have real consequences.</p>
<h2>Technology stack</h2>
<p>This project began with Python-based Jupyter Notebooks, and the use of Plotly, "the leading front-end for ML and data science models in Python, R, and Julia." But I needed a way for this to be accessible to the public, so I moved it onto the Django web framework. Django encourages rapid development and clean, pragmatic design. To bootstrap the initial dashboard grid we used Appseed and Bootstrap 4 for custom UI where we needed it.</p>
<figure><img alt="Tablet view of the COVID-19 dashboard home page" loading="lazy" width="1290" height="846" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.10~lrsj-3_vev.png&amp;w=1920&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.10~lrsj-3_vev.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftablet.10~lrsj-3_vev.png&amp;w=3840&amp;q=75"><figcaption><p>Tablet view of the dashboard's home page. The application is designed to be
responsive to all platforms and devices.</p></figcaption></figure>
<h2>Front-end design</h2>
<p>Overall the general approach of the application is to display a grid of different cards. The cards represent different forms of data organized in their respective way, and the user can interact with the data in several ways. We have a map card that uses COVID case data stacked on top of GPS coordinates. In another card, we have a plot that shows the overall trajectory of confirmed cases using time-series data with dates.</p>
<p>I designed the dashboard with a mobile-first approach, ensuring the layout worked across viewports. Plotly and Mapbox already handle multi-touch interactions, so most of the work was making the overall grid adaptable. Bootstrap 4 made that responsive structure much easier.</p>
<figure><img alt="Mobile views of the COVID-19 dashboard" loading="lazy" width="953" height="705" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.0o4fuy3deic6-.png&amp;w=1080&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.0o4fuy3deic6-.png&amp;w=1920&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fphones.0o4fuy3deic6-.png&amp;w=1920&amp;q=75"><figcaption><p>Mobile view of application, including list of key statistics, the map of
daily growth, and the fully interactive map made using Mapbox.</p></figcaption></figure>
<h2>How it works</h2>
<p>The following is a snippet of how we're using Python to scrape the data from different sources and return that data to the front-end to create data visualizations with Plotly. Using AJAX requests allows us to load the data asynchronously, which is a great way to improve the user experience by significantly reducing the initial page load time.</p>
<p>Note that the example code is incomplete for concision.</p>
<h3>1. Web scraping with Pandas</h3>
<p>Here we defined a simple function that reads from a specific URL that contains a CSV of raw data, we convert it to a Pandas data frame and return it.</p>
<pre class="language-python"><span class="code-block-label font-sans text-sm font-semibold text-white/90">Python</span><code class="language-python code-highlight"><span class="code-line line-number" line="1"><span class="token keyword">import</span> pandas <span class="token keyword">as</span> pd
</span><span class="code-line line-number" line="2">
</span><span class="code-line line-number" line="3"><span class="token keyword">def</span> <span class="token function">confirmed_report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
</span><span class="code-line line-number" line="4">  <span class="token comment"># Returns time series version of total cases confirmed globally</span>
</span><span class="code-line line-number highlight-line" line="5">  df <span class="token operator">=</span> pd<span class="token punctuation">.</span>read_csv<span class="token punctuation">(</span><span class="token string">'https://raw...CSSEGISandData/...csv'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="6">  <span class="token keyword">return</span> df
</span></code></pre>
<h3>2. Data cleaning &amp; formatting</h3>
<p>Now we define the function realtime_growth which cleans and manipulates the data frame returned from the above function. We need to do this because the data is not in the format we want, and we need to clean it up.</p>
<pre class="language-python"><span class="code-block-label font-sans text-sm font-semibold text-white/90">Python</span><code class="language-python code-highlight"><span class="code-line line-number" line="1"><span class="token keyword">def</span> <span class="token function">realtime_growth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
</span><span class="code-line line-number" line="2">  df1 <span class="token operator">=</span> confirmed_report<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span>confirmed_report<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>columns<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token builtin">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="3">  df2 <span class="token operator">=</span> deaths_report<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span>deaths_report<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>columns<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token builtin">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="4">
</span><span class="code-line line-number highlight-line" line="5">  growth_df <span class="token operator">=</span> pd<span class="token punctuation">.</span>DataFrame<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</span><span class="code-line line-number highlight-line" line="6">  growth_df<span class="token punctuation">[</span><span class="token string">'Confirmed'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> growth_df<span class="token punctuation">[</span><span class="token string">'Deaths'</span><span class="token punctuation">]</span> <span class="token operator">=</span> df1<span class="token punctuation">,</span> df2
</span><span class="code-line line-number highlight-line" line="7">  growth_df<span class="token punctuation">.</span>index <span class="token operator">=</span> growth_df<span class="token punctuation">.</span>index<span class="token punctuation">.</span>rename<span class="token punctuation">(</span><span class="token string">'Date'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="8">
</span><span class="code-line line-number" line="9">  yesterday <span class="token operator">=</span> pd<span class="token punctuation">.</span>Timestamp<span class="token punctuation">(</span><span class="token string">'now'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>date<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> pd<span class="token punctuation">.</span>Timedelta<span class="token punctuation">(</span>days<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="10">
</span><span class="code-line line-number" line="11">  <span class="token keyword">return</span> growth_df
</span></code></pre>
<h3>3. Sending AJAX request</h3>
<p>Using AJAX in JavaScript to send an asynchronous request to the Python backend. If successful then we create the data visualization (in this case, a scatter plot with visible line traces) using plotly.js.</p>
<pre class="language-js"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-js code-highlight"><span class="code-line"><span class="token keyword">function</span> <span class="token function">load_realtime_growth_chart</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">  <span class="token keyword">var</span> xhttp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line">  xhttp<span class="token punctuation">.</span><span class="token method-variable function-variable method function property-access">onreadystatechange</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">    <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">readyState</span> <span class="token operator">==</span> <span class="token number">4</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">status</span> <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class="code-line">      <span class="token comment">/* plotly.js code here*/</span>
</span><span class="code-line">    <span class="token punctuation">}</span>
</span><span class="code-line">  <span class="token punctuation">}</span>
</span><span class="code-line">  xhttp<span class="token punctuation">.</span><span class="token method function property-access">open</span><span class="token punctuation">(</span><span class="token string">'GET'</span><span class="token punctuation">,</span> <span class="token string">'realtime_growth'</span><span class="token punctuation">)</span>
</span><span class="code-line">  xhttp<span class="token punctuation">.</span><span class="token method function property-access">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class="code-line"><span class="token punctuation">}</span>
</span></code></pre>
<h3>4. Plotly to visualize the data</h3>
<p>We then create the D3.js-based line and scatter plots in JavaScript using Plotly. This creates an interactive, scientific data visualization easily on the Web browser. This one will probably be the most complex-looking part of the code because it takes a lot of tweaking to get the plot to your desired look and feel. But trust me it's simpler than it looks.</p>
<p>Visit <a href="https://plotly.com/python/">plot.ly</a> for docs and examples.</p>
<pre class="language-js"><span class="code-block-label font-sans text-sm font-semibold text-white/90">JavaScript</span><code class="language-js code-highlight"><span class="code-line line-number highlight-line" line="1"><span class="token keyword">var</span> plot_data <span class="token operator">=</span> <span class="token punctuation">[</span>confirmed_trace<span class="token punctuation">,</span> deaths_trace<span class="token punctuation">]</span>
</span><span class="code-line line-number highlight-line" line="2"><span class="token keyword">var</span> plot_layout <span class="token operator">=</span> <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="3">  <span class="token literal-property property">yaxis</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">automargin</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'log'</span><span class="token punctuation">,</span> <span class="token literal-property property">gridcolor</span><span class="token operator">:</span> <span class="token string">'#32325d'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="4">  <span class="token literal-property property">xaxis</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">automargin</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token literal-property property">showgrid</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="5">  <span class="token literal-property property">showlegend</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="6">  <span class="token literal-property property">hovermode</span><span class="token operator">:</span> <span class="token string">'closest'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="7">  <span class="token literal-property property">updatemenus</span><span class="token operator">:</span> <span class="token punctuation">[</span>
</span><span class="code-line line-number" line="8">    <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="9">      <span class="token literal-property property">visible</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="10">      <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'dropdown'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="11">      <span class="token literal-property property">buttons</span><span class="token operator">:</span> <span class="token punctuation">[</span>
</span><span class="code-line line-number" line="12">        <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="13">          <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'relayout'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="14">          <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Logarithmic'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="15">          <span class="token literal-property property">args</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token string-property property">'yaxis.type'</span><span class="token operator">:</span> <span class="token string">'log'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="16">        <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="17">        <span class="token punctuation">{</span>
</span><span class="code-line line-number" line="18">          <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'relayout'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="19">          <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Linear'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="20">          <span class="token literal-property property">args</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token string-property property">'yaxis.type'</span><span class="token operator">:</span> <span class="token string">'linear'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="21">        <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="22">      <span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="23">      <span class="token literal-property property">x</span><span class="token operator">:</span> <span class="token number">0.05</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="24">      <span class="token literal-property property">xanchor</span><span class="token operator">:</span> <span class="token string">'auto'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="25">      <span class="token literal-property property">bgcolor</span><span class="token operator">:</span> <span class="token string">'#6236FF'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="26">      <span class="token literal-property property">bordercolor</span><span class="token operator">:</span> <span class="token string">'rgba(0,0,0,0)'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="27">    <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="28">  <span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number" line="29"><span class="token punctuation">}</span>
</span></code></pre>
<h2>Wrapping things up</h2>
<p>The result is a set of real-time visualizations that work across devices and respond to both mouse and touch. Nothing fancy, just Python, Django, and Plotly running on the web, where anyone can open a link and explore the data.</p>
<p>Did it meet the original goal? Yes, and then some. The dashboard drew over 200k visits, which still feels surreal. What I remember most is that people actually used it — and hopefully walked away with a clearer picture of what was happening during the pandemic.</p>
<p>If you're a developer and want to dig into the code, check out the <a href="https://github.com/BrianRuizy/covid19-dashboard/#getting-started">getting started</a> docs in the GitHub repository.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Moving Into My Dream NYC Apartment as a Software Engineer]]></title>
            <link>https://b-r.io/posts/moving-into-my-dream-nyc-apartment</link>
            <guid isPermaLink="false">https://b-r.io/posts/moving-into-my-dream-nyc-apartment</guid>
            <pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>This is my second place in the city in just under two years. After a rough stretch getting here, I walk through how this apartment came to be, the move-in, and how I'm settling in: unpacking, setting up a workspace, and finding a new routine.</p>
<p>Also, take <span class="font-serif italic">dream apartment</span> with a grain of salt. Six hundred square feet is still six hundred square feet. What makes it feel like one is the view: I never imagined looking straight at the Empire State Building from home. More than that, location is everything right now. Walk downstairs and the city is already happening: good food, creativity, people from all walks of life. I couldn't be happier.</p>
<p>Anyway, here's the video. Hope you enjoy it :)</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[My Desk Setup for 2023. Minimalist but functional.]]></title>
            <link>https://b-r.io/posts/my-desk-setup-for-2023</link>
            <guid isPermaLink="false">https://b-r.io/posts/my-desk-setup-for-2023</guid>
            <pubDate>Tue, 17 Oct 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>I've already created a video covering my desk setup. If you'd rather watch that, use the card below. This post is the written companion with all the links and resources in one place.</p>
<p>To provide some background, I'm a software engineer by day and part-time creator in the evenings. I spend a lot of hours at this desk coding, editing, and learning, so I put together a setup that works for both.</p>
<a href="https://www.youtube.com/watch?v=Q9Qu-ddjDEE" target="_blank" rel="noopener noreferrer" class="not-prose my-10 flex flex-row items-center gap-4 rounded-2xl bg-background p-4 ring-1 ring-border sm:gap-6 sm:p-6"><div class="min-w-0 flex-1 space-y-1.5"><div class="flex items-center gap-2 text-sm leading-6 text-muted-foreground"><span class="line-clamp-1">youtube.com</span><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4 shrink-0"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25"></path></svg></div><div class="line-clamp-2 font-semibold text-foreground">Software Engineer's Productive and Minimal Desk Setup (2023)</div><p class="line-clamp-2 text-muted-foreground">A deep dive into the tech gadgets and home office products that make up this workspace.</p></div><div class="h-24 w-24 shrink-0 overflow-hidden rounded-xl md:w-48"><img alt="" loading="lazy" width="640" height="360" decoding="async" data-nimg="1" class="h-full w-full object-cover" style="color:transparent" sizes="(max-width: 768px) 96px, 192px" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=32&amp;q=75 32w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=48&amp;q=75 48w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=64&amp;q=75 64w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=96&amp;q=75 96w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=128&amp;q=75 128w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=256&amp;q=75 256w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=384&amp;q=75 384w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fthumbnail.0ij9dzgr6clj7.png&amp;w=3840&amp;q=75"></div></a>
<h2>The Desk</h2>
<p>First things first: the desk. It's the centerpiece of the setup. I got to test the <a href="https://shrsl.com/49346">Ergonofis Sway Desk</a>, which was gifted to me. It's a game-changer, with a slick control interface and aesthetics that match the functionality. They also built in an anti-collision system.</p>
<p>The Ergonofis team also sent their solid wood monitor riser / desk shelf. Having your monitor at eye level is better for posture, and the shelf is a clean way to get there while adding some style.</p>
<ul>
<li><a href="https://shrsl.com/49346">Ergonofis Sway Desk</a>: A versatile standing desk with intuitive preset heights</li>
<li><a href="https://shrsl.com/49342">Ergonofis Desk Shelf</a>: Solid wood shelf to elevate the display</li>
<li><a href="https://shrsl.com/4933x">Ergonofis Cable Management</a>: Keeps the underside tidy</li>
</ul>
<div class="not-prose my-8"><div class="relative md:-mx-12 md:px-12"><div class="overflow-hidden rounded-3xl bg-muted"><div class="flex cursor-grab active:cursor-grabbing"><div class="shrink-0 grow-0" style="width:100%"><img alt="Desk setup with cable management rack" draggable="false" width="4240" height="2832" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00166.0h5-mt7u4k9-r.jpg&amp;w=3840&amp;q=75"></div><div class="shrink-0 grow-0" style="width:100%"><img alt="Desk shelf and white oak surface" draggable="false" loading="lazy" width="4240" height="2832" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00150.0dfbcoc-rfsr-.jpg&amp;w=3840&amp;q=75"></div><div class="shrink-0 grow-0" style="width:100%"><img alt="Desk setup underside and cable management" draggable="false" loading="lazy" width="4240" height="2832" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC00160.030yac5poijnk.jpg&amp;w=3840&amp;q=75"></div><div class="shrink-0 grow-0" style="width:100%"><img alt="Full desk setup with white oak and white combo" draggable="false" loading="lazy" width="2048" height="1363" decoding="async" data-nimg="1" class="pointer-events-none aspect-3/2 h-auto w-full object-cover" style="color:transparent" sizes="(min-width: 768px) 672px, 100vw" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FDSC_3253.088v43x92bfbg.jpg&amp;w=3840&amp;q=75"></div></div></div><button type="button" aria-label="Previous image" disabled="" class="absolute top-1/2 z-10 hidden size-9 -translate-y-1/2 items-center justify-center rounded-full bg-card text-foreground shadow-md ring-1 shadow-foreground/5 ring-border transition hover:bg-muted disabled:pointer-events-none disabled:opacity-30 md:flex dark:bg-muted dark:hover:bg-muted/80 left-0"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"></path></svg></button><button type="button" aria-label="Next image" class="absolute top-1/2 z-10 hidden size-9 -translate-y-1/2 items-center justify-center rounded-full bg-card text-foreground shadow-md ring-1 shadow-foreground/5 ring-border transition hover:bg-muted disabled:pointer-events-none disabled:opacity-30 md:flex dark:bg-muted dark:hover:bg-muted/80 right-0"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"></path></svg></button></div><figcaption class="mt-4 text-sm leading-6 text-pretty text-muted-foreground/75">Captures of the setup, including the cable management rack and desk shelf. I went with the white oak and white color combo.</figcaption><div class="mt-4 flex items-center justify-center gap-1"><button type="button" aria-label="Image 1 of 4" aria-current="true" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground"></span></button><button type="button" aria-label="Image 2 of 4" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground/20 group-hover:bg-foreground/45"></span></button><button type="button" aria-label="Image 3 of 4" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground/20 group-hover:bg-foreground/45"></span></button><button type="button" aria-label="Image 4 of 4" class="group flex size-6 items-center justify-center"><span class="size-2 rounded-full transition bg-foreground/20 group-hover:bg-foreground/45"></span></button><span class="sr-only">Image <!-- -->1<!-- --> of <!-- -->4</span></div></div>
<h2>Monitors and Lighting</h2>
<p>A high-quality monitor matters for my work, and I chose the LG 34WN780. Its ergonomic stand gives full control over screen positioning. I also added the BenQ ScreenBar Halo, a USB-powered lamp that gives consistent, glare-free light across the desk.</p>
<ul>
<li><a href="https://amzn.to/3DJd86G">LG 34WN780 Monitor</a>: Strong monitor with ergonomic versatility</li>
<li><a href="https://amzn.to/3fUAfCi">BenQ ScreenBar Halo</a>: USB-powered lamp for consistent desk illumination</li>
</ul>
<h2>Computer Setup</h2>
<p>My primary machine is the 16-inch MacBook Pro. To streamline connections and cut cable clutter, I use an Anker USB-C hub. For audio, I reach for AirPods Max when I want to focus without distractions.</p>
<ul>
<li><a href="https://amzn.to/41fkhEH">16-inch MacBook Pro</a>: Reliable laptop for day-to-day work</li>
<li><a href="https://amzn.to/3Dk9vCV">Anker USB-C Hub</a>: Simplifies connections for a cleaner desk</li>
<li><a href="https://nomadgoods.com/products/stand-one-silver">Nomad MagSafe Dock</a>: Premium dock for MagSafe-compatible devices</li>
</ul>
<h2>Audio</h2>
<p>I prefer headphones over the monitor speakers. AirPods Max are the main pair for quality and focus.</p>
<ul>
<li><a href="https://amzn.to/3mie64b">AirPods Max</a>: Primary headphones for deep work</li>
<li><a href="https://amzn.to/3UmMQhq">Apple AirPods Pro</a>: Compact earbuds for lighter tasks</li>
<li><a href="https://amzn.to/46h5E6H">Sonos Beam Soundbar</a>: Wall-mounted soundbar when I want the room to feel like a mini theater</li>
</ul>
<h2>Peripherals</h2>
<p>I'm a mechanical keyboard enthusiast, and my favorite at the time was the Envoy by Mode Designs. Paired with the GMK Dracula keycap set and a Tomorrow-themed set, it added a personal touch. For pointing, I used the Logitech MX Master III for the extra buttons and ergonomics.</p>
<ul>
<li><a href="https://amzn.to/3Dm37eu">Orbitkey Desk Mat</a>: Desk mat with built-in storage</li>
<li><a href="http://modedesigns.com">Mode Envoy Keyboard</a>: Favorite keyboard of that year</li>
<li><a href="https://modedesigns.com/products/alexotos-edition-switches">Alexotos Linear Switches</a>: Smooth linear switches; I get a lot of compliments on the sound</li>
<li><a href="https://geekhack.org/">GMK Dracula Keycap Set</a>: Custom keycaps with a personal look</li>
<li><a href="https://amzn.to/3U5syHG">Logitech MX Master III</a>: Productive, ergonomic mouse</li>
<li><a href="https://amzn.to/46gxWyf">Magic Trackpad</a>: Gesture-friendly alternative to a traditional mouse</li>
</ul>
<h2>Chair and Ergonomics</h2>
<p>For long sessions, I chose the Herman Miller Aeron. Fully adjustable, with lumbar support that keeps posture comfortable through the day.</p>
<ul>
<li><a href="https://www.hermanmiller.com">Herman Miller Aeron Chair</a>: Ergonomic chair built for long hours</li>
</ul>
<h2>Miscellaneous Items</h2>
<p>A few extras that round out the workspace:</p>
<ul>
<li><a href="https://www.ikea.com/us/en/p/skadis-pegboard-white-10321618/">Ikea Pegboard</a>: Keeps essentials within reach</li>
<li><a href="https://amzn.to/46m0CA">Govee RGB Floor Lamp</a>: Ambient lighting for the room</li>
<li><a href="https://amzn.to/46CdXK8">Fellow Products Coffee Grinder</a>: For a better cup at the desk</li>
<li><a href="https://amzn.to/46fGa9M">Electric Kettle</a>: Quick brewing</li>
<li><a href="https://amzn.to/48HyP4v">Larq Water Bottle</a>: Self-cleaning bottle for all-day hydration</li>
</ul>
<h2>Conclusion</h2>
<p>That was the 2023 workspace. I've since moved and updated parts of the setup (see the later NYC desk tour), but this one still captures where I was that year: minimal, functional, and tuned for long coding and creating sessions.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[My Desk Setup Tour in NYC]]></title>
            <link>https://b-r.io/posts/my-desk-setup-tour-in-nyc</link>
            <guid isPermaLink="false">https://b-r.io/posts/my-desk-setup-tour-in-nyc</guid>
            <pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>A walkthrough of the desk I use in New York for coding, editing, and long creative sessions — focused on comfort, cable management, and keeping the setup simple.</p>
<p>If you want the written gear list, it’s on my <a href="/uses">uses</a> page.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[My New Life Living in NYC as a Software Engineer]]></title>
            <link>https://b-r.io/posts/my-new-life-living-in-nyc-as-a-software-engineer</link>
            <guid isPermaLink="false">https://b-r.io/posts/my-new-life-living-in-nyc-as-a-software-engineer</guid>
            <pubDate>Mon, 25 Nov 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>The early days of living in New York as a software engineer — settling in, building a rhythm, and figuring out how work and creative projects fit into city life.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[The Notion System I Actually Use as a Developer and Creator]]></title>
            <link>https://b-r.io/posts/my-notion-productivity-setup</link>
            <guid isPermaLink="false">https://b-r.io/posts/my-notion-productivity-setup</guid>
            <pubDate>Tue, 19 Mar 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>I’ve been using Notion for years. What started as a simple note-taking app became the system I use for content creation, development work, learning, and personal projects.</p>
<p>I get a lot of questions about the templates, so this post breaks down the ones that actually matter day to day. There’s also a <a href="https://www.youtube.com/watch?v=53KFVt2GRkE">video walkthrough</a> if you’d rather see the workspace in motion.</p>
<a href="https://www.youtube.com/watch?v=53KFVt2GRkE" target="_blank" rel="noopener noreferrer" class="not-prose my-10 flex flex-row items-center gap-4 rounded-2xl bg-background p-4 ring-1 ring-border sm:gap-6 sm:p-6"><div class="min-w-0 flex-1 space-y-1.5"><div class="flex items-center gap-2 text-sm leading-6 text-muted-foreground"><span class="line-clamp-1">youtube.com</span><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="size-4 shrink-0"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25"></path></svg></div><div class="line-clamp-2 font-semibold text-foreground">My Complete Notion Setup (2024) — Templates &amp; Systems</div><p class="line-clamp-2 text-muted-foreground">A tour of my Notion workspace, including templates for content creation, development work, and personal productivity systems.</p></div><div class="h-24 w-24 shrink-0 overflow-hidden rounded-xl md:w-48"><img alt="" loading="lazy" width="320" height="180" decoding="async" data-nimg="1" class="h-full w-full object-cover" style="color:transparent" sizes="(max-width: 768px) 96px, 192px" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=32&amp;q=75 32w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=48&amp;q=75 48w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=64&amp;q=75 64w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=96&amp;q=75 96w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=128&amp;q=75 128w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=256&amp;q=75 256w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=384&amp;q=75 384w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=750&amp;q=75 750w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=828&amp;q=75 828w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=1080&amp;q=75 1080w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=1200&amp;q=75 1200w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=1920&amp;q=75 1920w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=2048&amp;q=75 2048w, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=3840&amp;q=75 3840w" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnotion-setup-thumbnail.06cu5wjxugax2.png&amp;w=3840&amp;q=75"></div></a>
<h2>Full-stack developer roadmap</h2>
<figure><img alt="Full stack developer roadmap in Notion" loading="lazy" width="1920" height="1080" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Froadmap.0eig0x2gztsk~.png&amp;w=1920&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Froadmap.0eig0x2gztsk~.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Froadmap.0eig0x2gztsk~.png&amp;w=3840&amp;q=75"><figcaption><p>A self-paced overview of what to learn as a full-stack web developer.</p></figcaption></figure>
<p>This roadmap gives a general overview of full-stack development without pretending to be a complete tutorial. It’s organized into chapters and modules — Fundamentals, Frontend, Backend, Databases — with curated resources so you can move at your own pace.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brianroadmap"><p>🧭 Start learning</p></a></div>
<h2>Content Manager OS</h2>
<figure><img alt="Content Manager OS Notion template" loading="lazy" width="1920" height="1080" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcontent-manager.16tkqwtiux73y.png&amp;w=1920&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcontent-manager.16tkqwtiux73y.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcontent-manager.16tkqwtiux73y.png&amp;w=3840&amp;q=75"><figcaption><p>The operating system behind my content workflow. This is the only paid template in the list — the rest are free.</p></figcaption></figure>
<p>This is home base for content creation: projects, tasks, partners, and earnings. I’ve used it since the first video on the channel. Good content starts with clear writing and planning, and this template keeps research, production, and partnerships in one place.</p>
<p>It’s flexible enough for YouTube, writing, or other formats. Building the system once saved me from reinventing it every time a new project started.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brcontentmanager"><p>🖼️ Start creating</p></a></div>
<h2>App development notes</h2>
<p>This is my personal worklog for standups, sprint planning, postmortems, and weekly notes. Team task tracking lives elsewhere — this space is for preserving context and making past decisions easier to find. Notion’s AI summary and Q&amp;A features are especially useful here.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brappnotes"><p>💻 Get the template</p></a></div>
<h2>Personal finance</h2>
<p>A simple budget and recurring-expense tracker with table calculations, categories, and tags. I don’t use it as heavily anymore — Notion isn’t ideal for granular money tracking when income and spend aren’t perfectly consistent — but it’s still a solid lightweight option.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brpersonalfinance"><p>💷 Get the template</p></a></div>
<h2>Reading list</h2>
<p>Built around the Notion Web Clipper. It’s not perfect, but it’s fast: turn any page into something readable and open it on any device later.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brreadinglist"><p>📚 Get the template</p></a></div>
<h2>Snippets</h2>
<p>A home for email templates and other text I reuse often. I’d like to add a quick fill-in-variables → copy-to-clipboard flow eventually.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brsnippets"><p>🔗 Get the template</p></a></div>
<h2>LeetCode template</h2>
<p>Interview practice without pure memorization: define the problem, capture the thought process, sketch on a whiteboard block, add code, and note complexity. It keeps practice problems organized in one place.</p>
<div class="not-prose my-6"><a class="inline-flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium outline-offset-2 transition-all active:not-aria-[haspopup]:translate-y-px bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground" target="_blank" rel="noopener noreferrer" href="https://ntn.so/brleetcode"><p>💻 Get the template</p></a></div>
<hr>
<p>These templates have been the backbone of how I stay organized. They’re not perfect, and they keep changing — grab what helps and make it yours.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Why I Stripped My Personal Website Down]]></title>
            <link>https://b-r.io/posts/my-website-refresh</link>
            <guid isPermaLink="false">https://b-r.io/posts/my-website-refresh</guid>
            <pubDate>Sat, 03 May 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>I used to wonder why my professors kept such simple websites—just lists of
publications and projects. Now I understand: they focused on their work and let
it speak for itself.</p>
<p>For a long time, I treated my own site like a sandbox. It accumulated
half-finished posts, scattered components, and experiments without a clear
purpose. Instead of helping me share my work, it started to feel distracting
and directionless.</p>
<blockquote>
<p>There's a tremendous power in using the least amount of information to get a
point across.</p>
</blockquote>
<p>That idea shaped this version of my personal website. Rather than implementing
every new interface trend that catches my attention, I'm focusing on what
matters most: curating my work, keeping useful references, and making it easy to
find the things I want to share.</p>
<p>I still enjoy experimenting with new web technologies, but those experiments
don't all need to live in the same place. This site can be quieter—a focused
home for my work, writing, and the occasional life update.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[Realistic Day in the Life of a Software Engineer in NYC]]></title>
            <link>https://b-r.io/posts/realistic-day-in-the-life-of-a-software-engineer-in-nyc</link>
            <guid isPermaLink="false">https://b-r.io/posts/realistic-day-in-the-life-of-a-software-engineer-in-nyc</guid>
            <pubDate>Wed, 21 May 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>Not a highlight reel. I talk about some real challenges I've been going through that have gotten in the way of my video-making process — but you still have to get up and go. Here's a quick day-in-the-life of what I've been up to lately: picking up some new camera gear, a workout, a new mobile app I'm building that I'm excited to announce, and some downtime at the Chelsea Piers.</p>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
        <item>
            <title><![CDATA[This App Got Us 1st Place at a Microsoft Hackathon]]></title>
            <link>https://b-r.io/posts/this-app-got-us-1st-place-at-a-microsoft-hackathon</link>
            <guid isPermaLink="false">https://b-r.io/posts/this-app-got-us-1st-place-at-a-microsoft-hackathon</guid>
            <pubDate>Sun, 15 Dec 2019 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<h2>The Challenge</h2>
<p>A group of college friends and I signed up for what we thought would be a fun weekend experiment. The 2019 Smart Infrastructure Hackathon at The Cannon in Houston, in partnership with Microsoft Azure, asked teams to build solutions for improving US city infrastructure. We had 24 hours, coffee, and a room full of cloud solution architects when we got stuck.</p>
<h2>Our Idea</h2>
<p>After kicking around a few concepts, we landed on road potholes. They cost American drivers $6.4 billion per year in repairs and insurance. Fixing one runs about $30–$50; letting it sit can cost a driver closer to $300 a year. The math made it worth building for.</p>
<p>Our pitch was a two-layer detection system:</p>
<ul>
<li><strong>Layer 1:</strong> Dashcam footage analyzed in real time with computer vision</li>
<li><strong>Layer 2:</strong> Phone telemetry to confirm abrupt movement on the road</li>
</ul>
<p>Confirmed potholes would plot on a map for cities to act on. The driver UI would stay minimal: a quick confirmation prompt, nothing that pulls attention off the road.</p>
<h2>How We Built It</h2>
<p>Python on Microsoft Azure, end to end. Four moving parts:</p>
<figure><img alt="Tech stack" loading="lazy" width="1000" height="600" decoding="async" data-nimg="1" class="bg-transparent" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftech.02w1av0fjpdww.webp&amp;w=1080&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftech.02w1av0fjpdww.webp&amp;w=2048&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftech.02w1av0fjpdww.webp&amp;w=2048&amp;q=75"></figure>
<h3>1. Mobile telemetry</h3>
<p>On Android, we used a publicly available sensor logging app with developer-friendly CSV export. While driving test routes, it recorded GPS coordinates, accelerometer readings on all three axes, and timestamps. Same raw device data you'd get from developer tooling, just packaged for quick export off the phone.</p>
<p>In Python, pandas ingested those CSVs and matplotlib helped us spot patterns. The main challenge was false positives: not every jolt is a pothole. Plotting accelerometer readings over time let us tune the threshold before sending a hit downstream.</p>
<pre class="language-python"><span class="code-block-label font-sans text-sm font-semibold text-white/90">Python</span><code class="language-python code-highlight"><span class="code-line line-number" line="1"><span class="token keyword">import</span> pandas <span class="token keyword">as</span> pd
</span><span class="code-line line-number" line="2"><span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt
</span><span class="code-line line-number" line="3">
</span><span class="code-line line-number" line="4">df <span class="token operator">=</span> pd<span class="token punctuation">.</span>read_csv<span class="token punctuation">(</span><span class="token string">'/home/br/Downloads/testdata.csv'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="5">df<span class="token punctuation">[</span><span class="token string">'Time'</span><span class="token punctuation">]</span> <span class="token operator">=</span> pd<span class="token punctuation">.</span>to_datetime<span class="token punctuation">(</span>df<span class="token punctuation">.</span>Time<span class="token punctuation">,</span> <span class="token builtin">format</span><span class="token operator">=</span><span class="token string">'%Y-%m-%d %H:%M:%S:%f'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="6">
</span><span class="code-line line-number" line="7">columns <span class="token operator">=</span> <span class="token punctuation">[</span>
</span><span class="code-line line-number highlight-line" line="8">  <span class="token string">'ACCELEROMETER X (m/s²)'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="9">  <span class="token string">'ACCELEROMETER Y (m/s²)'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="10">  <span class="token string">'ACCELEROMETER Z (m/s²)'</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="11">  <span class="token string">'Time'</span>
</span><span class="code-line line-number" line="12"><span class="token punctuation">]</span>
</span><span class="code-line line-number" line="13">
</span><span class="code-line line-number" line="14">df<span class="token punctuation">[</span>columns<span class="token punctuation">]</span><span class="token punctuation">.</span>plot<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token string">'Time'</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="15">plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre>
<h3>2. Live computer vision</h3>
<p>This was the harder layer, and where the Azure architects helped most.</p>
<p>The idea was straightforward: mount a phone on the dash, record the road ahead, and let a vision model look for pothole-shaped disruptions in the pavement. Azure Logic Apps watched for incoming frames and pushed them into the cloud. From there, OpenCV handled basic preprocessing (cropping the road surface, normalizing lighting) before handing images off to Azure Computer Vision for analysis.</p>
<p>In a full production version, each frame would get scored for surface anomalies. A high-confidence visual hit plus a matching accelerometer spike from Layer 2 would trigger the confirmation prompt. Either signal alone might be noise; together they made the detection feel much more reliable.</p>
<p>We didn't get the whole pipeline polished in 24 hours, but we proved the concept: frames in, analysis out, tied back to what the phone sensors were already seeing.</p>
<figure><img alt="Dashcam footage concept" loading="lazy" width="1000" height="600" decoding="async" data-nimg="1" style="color:transparent" src="https://miro.medium.com/max/1200/0*KS2_n2hz7Lrqyn_L.gif"><figcaption><p>Dashcam footage concept: live capture and pothole prediction on the road.</p></figcaption></figure>
<h3>3. The Interface</h3>
<p>One job: show a dialog when the system flagged a pothole, let the driver confirm or dismiss. We ran out of time to wire up both backend and frontend, but I mocked up the intent: minimal, glanceable, and safe while driving.</p>
<figure><img alt="UI mockup" loading="lazy" width="1080" height="799" decoding="async" data-nimg="1" class="bg-muted" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmockup-clear.0vizsgzbl~wpy.png&amp;w=1080&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmockup-clear.0vizsgzbl~wpy.png&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmockup-clear.0vizsgzbl~wpy.png&amp;w=3840&amp;q=75"><figcaption><p>A simple pop-up to confirm a pothole, designed to keep the driver's
attention on the road.</p></figcaption></figure>
<h3>4. Mapping</h3>
<p>For the backend, accurate geolocation was non-negotiable. A pothole report is only useful if a city crew can find it, and over a 24-hour hackathon we were collecting instances fast. Every confirmed hit needed a precise latitude, longitude, and timestamp so we could store it, deduplicate it, and eventually hand cities something actionable.</p>
<p>That is where clustering came in. One driver hitting the same rough patch might trigger a single spike. Several drivers reporting near the same coordinates over a few days starts to look like a real pothole. The backend grouped those nearby instances together instead of flooding the map with duplicate pins.</p>
<p>Folium handled the display layer: plot the collection of confirmed reports, cluster what overlaps, and give a quick visual read of where problems were stacking up. For the demo, that was enough to show how a city could prioritize repairs from crowdsourced data rather than waiting on manual inspection routes.</p>
<pre class="language-python"><span class="code-block-label font-sans text-sm font-semibold text-white/90">Python</span><code class="language-python code-highlight"><span class="code-line line-number" line="1"><span class="token keyword">import</span> folium
</span><span class="code-line line-number" line="2"><span class="token keyword">import</span> pandas <span class="token keyword">as</span> pd
</span><span class="code-line line-number" line="3">
</span><span class="code-line line-number" line="4">SF_COORDINATES <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token number">37.76</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">122.45</span><span class="token punctuation">)</span>
</span><span class="code-line line-number" line="5"><span class="token builtin">map</span> <span class="token operator">=</span> folium<span class="token punctuation">.</span>Map<span class="token punctuation">(</span>location<span class="token operator">=</span>SF_COORDINATES<span class="token punctuation">)</span>
</span><span class="code-line line-number" line="6">
</span><span class="code-line line-number" line="7"><span class="token keyword">for</span> each <span class="token keyword">in</span> df<span class="token punctuation">.</span>iterrows<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
</span><span class="code-line line-number highlight-line" line="8">  <span class="token builtin">map</span><span class="token punctuation">.</span>simple_marker<span class="token punctuation">(</span>
</span><span class="code-line line-number highlight-line" line="9">    location <span class="token operator">=</span> <span class="token punctuation">[</span>each<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'Y'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>each<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'X'</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class="code-line line-number highlight-line" line="10">    clustered_marker <span class="token operator">=</span> <span class="token boolean">True</span>
</span><span class="code-line line-number" line="11">  <span class="token punctuation">)</span>
</span><span class="code-line line-number" line="12">
</span><span class="code-line line-number" line="13">display<span class="token punctuation">(</span><span class="token builtin">map</span><span class="token punctuation">)</span>
</span></code></pre>
<figure><img alt="Map of San Francisco with potholes marked" loading="lazy" width="1000" height="600" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*PYSGLUaVid-vzeHr.png&amp;w=1080&amp;q=75 1x, /_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*PYSGLUaVid-vzeHr.png&amp;w=2048&amp;q=75 2x" src="/_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*PYSGLUaVid-vzeHr.png&amp;w=2048&amp;q=75"><figcaption><p>Potholes marked on a map of San Francisco. Clustered markers group nearby
reports into a single signal instead of scattered one-off pins.</p></figcaption></figure>
<h2>The Final Result</h2>
<p>When the countdown ended, we had enough working to demo the full loop in 24 hours, thanks to strong team collaboration and a lot of help from the Azure architecture team. The judges called a draw for first place, and we walked away with Azure credits and seats at the host company's co-working space to keep building.</p>
<p>Looking back, it was such a fun little challenge. Twenty-four hours is barely enough time to sleep, let alone wire up computer vision, sensor pipelines, and a map backend. But that constraint is part of what made it exciting. A small group of people with different skills can sit down, pick a real problem worth solving, and actually start building toward something that could matter outside the room. Potholes are boring until you put a dollar figure on them and realize cities need better data to fix them. That is what I remember most.</p>
<figure><img alt="The Bump.it team from UHD" loading="lazy" width="1000" height="600" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*v0plg9CmtcGd_IyZ.jpg&amp;w=1080&amp;q=75 1x, /_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*v0plg9CmtcGd_IyZ.jpg&amp;w=2048&amp;q=75 2x" src="/_next/image?url=https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0*v0plg9CmtcGd_IyZ.jpg&amp;w=2048&amp;q=75"><figcaption>The Bump.it team from UHD</figcaption></figure>]]></content:encoded>
            <author>brian@b-r.io (Brian Ruiz)</author>
        </item>
    </channel>
</rss>