<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Dillon Shook</title><description>Autodidact &amp; Zero One Infinity Advocate</description><link>https://dillonshook.com/</link><language>en</language><copyright>All content copyright Dillon Shook</copyright><item><title>Web 4.0</title><link>https://dillonshook.com/web-4/</link><guid isPermaLink="true">https://dillonshook.com/web-4/</guid><description>Do you dream of what the web could be? Here is my utopian vision...</description><pubDate>Wed, 29 Oct 2025 12:23:12 GMT</pubDate><content:encoded>&lt;p&gt;It’s safe to say that Web 3 was a flop already right? 😛  Anyways, this post is a vision of what could come next for the web, whatever version we’re on now…&lt;/p&gt;
&lt;p&gt;The other day I was trying to find a new React component library.  We’re using &lt;a href=&quot;https://www.radix-ui.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Radix&lt;/a&gt; right now but it’s a “headless” component library where you not only have to style everything yourself but also create wrapper components to encapsulate the complexity of all the sub components and customize them for all the missing behavior we need.  It’s no joke to make your own (good) component library that has a consistent interface for things like click events, form labels, validation states, disabled components, accessibility, etc, etc.  On top of all that Radix is also missing what I consider pretty table stakes components like a &lt;a href=&quot;https://component.gallery/components/combobox/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Combobox&lt;/a&gt; and multi-select field so you’re once again left to fend for yourself.&lt;/p&gt;
&lt;p&gt;So I spent the better part of a day looking for a new library.  I ended up combing through 11 of the most popular ones and for one reason or another they all pretty much got ruled out.  Some were missing basic components we needed, some didn’t support &lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SSR&lt;/a&gt;, some would be a big pain in the butt to customize the styling to match the rest of the site, some were using different styling technology than the rest of the app which would be a maintenance headache.&lt;/p&gt;
&lt;p&gt;All this got me thinking… &lt;strong&gt;How much time have we wasted re-inventing the wheel?&lt;/strong&gt;  Each of these libraries represents multiple thousands of hours of our collective development time, and there are hundreds of them just for React! Think about all the other frontend frameworks that have their own libraries, and then all the various desktop application frameworks that have been built over the years.  And how many different build chains have there been with how many hours sunk into churn?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wouldn’t it be nice if we had one amazing open source way to develop applications instead of thousands of half baked ways?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And yes, I know, I know…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xkcd.com/927/&quot; target=&quot;_blank&quot; class=&quot;no-styling&quot;&gt;&lt;img class=&quot;no-zoom !rounded-none&quot; alt=&quot;Standards&quot; src=&quot;https://imgs.xkcd.com/comics/standards.png&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But it still feels like we’re pre-industrial revolution times with everyone hand crafting their special parts. It’s high time we re-invested in some standardization. So to me that’s creating the next version of the web which puts us at 4.0 for whoever’s making up the version numbers.&lt;/p&gt;
&lt;p&gt;There was a good comment on Hacker News the other day that captures the feeling:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The reason the web changes so fast, and there are so many rewrites, is the same reason a puzzle whose pieces don’t fit together keeps getting shifted around and restarted.&lt;/p&gt;
&lt;p&gt;People are looking for a satisfying non-leaky abstraction to build upon and they don’t find it with web technologies. They get close, but those last few pieces never quite fit, and we lack the power to reshape the pieces, so we tear out all the pieces and try again. Maybe this next time we’ll find a better way to fit them together.&lt;/p&gt;
&lt;p&gt;— &lt;a href=&quot;https://news.ycombinator.com/item?id=45520631&amp;#x26;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Buttons840 on HN&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;isnt-this-what-your-os-should-do&quot;&gt;Isn’t this what your OS should do?&lt;a class=&quot;anchor&quot; href=&quot;#isnt-this-what-your-os-should-do&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some of you may be thinking that this is a job for your operating system, and it should be providing the tools to build applications easily on top of it.  The problem is that all the operating systems people use day to day are owned by companies with negative incentives to make open source cross platform tooling which means no cross platform apps.  The operating systems that &lt;em&gt;are&lt;/em&gt; open source have a &lt;a href=&quot;https://upload.wikimedia.org/wikipedia/commons/1/1b/Linux_Distribution_Timeline.svg?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;good history of re-inventing the wheel themselves&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides the fact it’s &lt;a href=&quot;https://news.ycombinator.com/item?id=45066395&amp;#x26;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pretty much impossible to create a new OS&lt;/a&gt; now, there’s never going to be a time where everyone is running the same OS anyways so we’re always going to need an application layer on top of OS that is one abstraction level higher that can hide the details of running on different operating systems.&lt;/p&gt;
&lt;p&gt;Native apps will always exist to push the boundaries of what’s possible on a platform, but most people and business don’t care about that and just want the easiest and most cost effective way to build cross platform apps that are easy to maintain across all the platforms. Plus, we still need a solution that scales from a static site that should load in 10’s of milliseconds all the way up to full featured apps.  The OS install and update process is a huge drag for native apps.  No one wants to install your personal home page.&lt;/p&gt;
&lt;h2 id=&quot;so-then-what&quot;&gt;So then what?&lt;a class=&quot;anchor&quot; href=&quot;#so-then-what&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m primarily a web developer, so what I’m thinking is of course shaped by what I know, but the web has been the most successful cross platform application platform ever created.  &lt;strong&gt;So what I want is like the web, but better. Re-imagined.&lt;/strong&gt; And suitable for building applications of all kinds, from the simplest static content sites to the most complex desktop apps you can think of like Photoshop or Excel. All with better performance, reduced development time, and more people rowing in the same direction than what’s happening today.&lt;/p&gt;
&lt;p&gt;Backwards compatibility has been one of the web’s greatest features for (checks wikipedia…) 34 years now! But it feels like we’re due for a breaking change reset that incorporates all we’ve learned in the last 3 decades and makes building apps for the next 6 decades faster, less bug prone, and easier than it is now.  I’m not a browser developer so I can only imagine how much cruft is hanging around slowing everything down to handle the bajillion edge cases for maintaining backwards compatibility for so long.&lt;/p&gt;
&lt;p&gt;So lets start laying down some details, even if they are a little vague &lt;strong&gt;because this is daydream not a design document.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;web-4-overview&quot;&gt;Web 4 Overview&lt;a class=&quot;anchor&quot; href=&quot;#web-4-overview&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;To put it simply: new protocol, new markup language, new scripting language, new styling language, new standard components, new mechanisms for data synchronization.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We’ll first need a new protocol to tell the recipient we’re sending data which needs to be interpreted differently by the browser which also requires new capabilities. There may need to be some new verbs introduced (see the &lt;a href=&quot;#backend&quot;&gt;Backend section&lt;/a&gt; ) but fundamentally it’ll be very similar to HTTP/3 under the hood.&lt;/p&gt;
&lt;p&gt;The rest will be very recognizable as upgrades to the existing way the web works. There will still be markup sent to define layout and maintain accessibility. There will still be a styling language to define the visual presentation. And there will still be an application language controlling both the markup and styling, as well as connecting to a backend to send and receive data.&lt;/p&gt;
&lt;p&gt;I just want everything more interoperable and cut from the same cloth.  Something that’s cohesively designed to work as well together as possible and lower the barrier to learning.&lt;/p&gt;
&lt;p&gt;Let’s start by looking at the markup.&lt;/p&gt;
&lt;h2 id=&quot;markup&quot;&gt;Markup&lt;a class=&quot;anchor&quot; href=&quot;#markup&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Have you ever wondered where HTML got the whole bracket and tag syntax from? I didn’t until just now when I was starting this section but apparently it was adopted from something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard%20Generalized%20Markup%20Language?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Standard Generalized Markup Language&lt;/a&gt; that was developed in the 60’s.&lt;/p&gt;
&lt;p&gt;Since we’re making a breaking change, now would be a good time to update the syntax to be much closer to the other languages we’ll need to use.  It’s tempting to think it’d be nice to just have one language for markup, styling, and application code, but there’s power and brevity in having domain specific languages for each so they can all focus on their individual task and keep separation of concerns.  Having said that though, there’s no reason the languages shouldn’t be from the same genealogy and share as much syntax as possible.&lt;/p&gt;
&lt;p&gt;Here’s a simple example:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;  dsml&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;en-US&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    head &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;      title &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;My First Web 4.0 Document!&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    body &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;      grid&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;columns&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; gap&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;        link&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;/blog&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;          img&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;            src&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;/picture.webp&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;            caption&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;My pretty picture&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;            zoomable&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;            sizes&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{{&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;400&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;/picture-400px.webp&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 1800&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;/picture-1800px.webp&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;          )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;        section&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;component&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;someNamespace&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F6F6F4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;SectionComponent&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;          p &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;Welcome to my site!&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;          button&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;variant&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;secondary&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;            &quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;Press the button, Max&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;      /* Oh wow, normal comments! */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;      someNamespace&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F6F6F4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;myCoolComponent&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{[&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;23&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;]})&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;        &quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;That has child text&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s a few things to notice here.  It’s similar to HTML, but instead of opening and closing tags with attributes, but now everything looks more like function calls with optional named arguments. That’s not a coincidence.  As you’ll see in the scripting section, everything is really a component, not just a tag.  Each component’s &lt;del&gt;attributes&lt;/del&gt; props can be any standard data type including objects (like the image sizes), not just strings. With this setup there’s also no more chance of mismatched closing tags, just mismatched brackets as in most languages but with editor formatters that’s a well handled problem.&lt;/p&gt;
&lt;p&gt;Most &lt;del&gt;tags&lt;/del&gt; components you’ll use will be from the standard library, and the intention is that you’ll be able to look up the source of each of the standard library components and see exactly how they’re implemented from primitives, as well as all the props they take to customize their functionality to suit your needs.&lt;/p&gt;
&lt;p&gt;If you do need a custom component, you’ll just specify the script as the component name which will bind it up to put whatever it renders in the right place in the DOM.  The children and props specified are the initial values the component scripts will use before they re-render.&lt;/p&gt;
&lt;h2 id=&quot;with-style&quot;&gt;With Style&lt;a class=&quot;anchor&quot; href=&quot;#with-style&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another big change from HTML/CSS as we know it is that here all style attributes can be passed as normal props.  This has some pretty cool advantages we’ll see in the scripting section but also allows seamlessly customizing components both in look and functionality in the same way.  Of course there will have to be good tooling support showing the reserved style attributes so you don’t accidentally create naming collisions with your custom props.  This format is also along the same lines of what Tailwind is trying to accomplish but having first class support support for it means you won’t have to learn two languages to do the same thing.&lt;/p&gt;
&lt;p&gt;Inline with my thoughts on Tailwind, there’s a breaking point for readability with how many props/classes should be on a component.  After about 10 or so, the complexity is sufficient to justify pulling the styles out into a separate styling section where you have both more power and more capability to organize and document the code for readability.  Styles should be scoped to components by default and only have the extra syntax to globally style the app for the more rare case when you need to do that.  For example, when you want to install a theme.  I can imagine sites popping up where you could download theme style sheets that completely change the look and feel of the standard library components that everyone should be using (anyone remember &lt;a href=&quot;https://csszengarden.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CSS Zen Garden&lt;/a&gt;?).&lt;/p&gt;
&lt;p&gt;Styles should also be able to override and customize every part of native components like the icons for checkboxes and the circles and dots for radio elements without completely replacing them like you have to do now.  Like I mentioned in the markup section you should be able to see the source for native components and see exactly what elements they’re rendering so you can style them.  Using real primitives everywhere should also reduce or completely eliminate the need for pseudo-elements like ::before &amp;#x26; ::after.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;scss&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;  /* Variables with the same syntax as your scripts */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#F286C4&quot;&gt;  var&lt;/span&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#F286C4&quot;&gt; padding-size&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; = 8px&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;  grid &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#97E1F1&quot;&gt;    background&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; gray&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#BF9EEE&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;800&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#97E1F1&quot;&gt;    border&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#8839EF;--shiki-dark:#F286C4&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#BF9EEE&quot;&gt; solid&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; gray&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#BF9EEE&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;900&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#97E1F1&quot;&gt;    padding&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; padding&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#BF9EEE&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;    /* Inline calculations with variables */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#97E1F1&quot;&gt;    margin&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; padding&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#BF9EEE&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;size &lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;    /* Conditionals also with the same syntax as your scripts */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    if(screen_width &amp;#x3C; 400px)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-dark:#97E1F1&quot;&gt;      padding&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#8839EF;--shiki-dark:#F286C4&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;  /* Selectors based on component props */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;  img(zoomable)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    rounded&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#F286C4&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here you can see the styling language looks similar to the markup language like selecting elements to style based on their current props. But it should also look like a subset of the scripting language and allow you to use the same syntax for variables and conditionals. TBD whether or not it’d be a good idea to allow loops in the style sheet. It could be useful for setting up variable state to use later, but also potentially hazardous to performance since loading the style sheets will still be a blocker to first render.  There definitely should be support for functions that apply styles though, a la &lt;a href=&quot;https://sass-lang.com/documentation/at-rules/mixin/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;sass mixins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To further intentionally blur the line between styles and scripts it should be easy to share your variables from scripts to styles or from styles to scripts. A good usecase for this I run into all the time is needing to share the color palette between scrips and styles without having to duplicate variables.  There’s a lot of cases where your scripts want to dynamically color something based on state and should be able to access color palette variables, potentially manipulate them, and then apply them back as styles while still having them be strongly typed like all the other scripting variables.&lt;/p&gt;
&lt;blockquote class=&quot;admonition bdm-tip&quot;&gt;&lt;span class=&quot;bdm-title&quot;&gt;TIP&lt;/span&gt;&lt;p&gt;Color manipulation in CSS has already come pretty far and you can do cool stuff like take one color in a variable and dynamically brighten and lower its opacity in one line:&lt;/p&gt;&lt;p&gt;&lt;code&gt;oklch(from var(--color) calc(l + 0.1) c h / calc(alpha - 0.1))&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Another big hole in CSS’ current capabilities is being able to define custom shaders (both geometry and vertex) for anything the browser draws. I found a couple decade old articles talking about this but apparently it never made it into the spec which is a shame.  You can do some basic stuff with the predefined &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_filter_effects/Using_filter_effects?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;filter and backdrop-filter&lt;/a&gt; properties but it’s so limiting. You can make some &lt;a href=&quot;https://www.shadertoy.com/browse?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;truly wild yet performant visuals&lt;/a&gt; with shaders and I’d love to see web designers explore a whole new domain of possibilities.  Think simulated material backgrounds that react to the cursor acting as light source. Think button borders that simulate pond ripples when you click them.  These are silly examples but there’s really infinite possibilities and so many creative people out there that I’d love to see what they come up with. It’d also make web games much richer without having to resort to rendering everything in a canvas.  All the shader effects would need to have fallback colors for accessibility and user preference reasons of course but I’d be leaving that setting on all day every day.&lt;/p&gt;
&lt;p&gt;There’s a huge grab bag of other stuff I’d like to see improved like native shadow presets (with simulated light source), easier to understand and use layer stacking than z-index, a better thought out &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/contrast-color?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;contrast color&lt;/a&gt;, anchor based positioning (put the top right of this box at the center of this other box), simplified naming (flexbox justify/align I’m looking at you), native nested selector support, etc, etc…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There’s a lot of innovation happening on the web in your style sheets right now!&lt;/strong&gt; I want to keep that up and encourage sites to look unique, personal, and an artistic expression of their creators.  This is still possible even with everyone using the same components for functionality under the hood.&lt;/p&gt;
&lt;h2 id=&quot;scripting&quot;&gt;Scripting&lt;a class=&quot;anchor&quot; href=&quot;#scripting&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To me it’s safe to say that the web has settled on components that rerender as a function of state for building applications.  React really did revolutionize web development with that idea (or at least popularizing it). For those of use who remember the before times, it was grim having to manually update the DOM when your state changed or you were reacting to user events.  The current situation is far from perfect though of course.&lt;/p&gt;
&lt;p&gt;The first sticking point we’d have to decide on to make it better is &lt;strong&gt;the language&lt;/strong&gt;.  If we’re pushing the reset button, we better re-evaluate what the best choice really is.&lt;/p&gt;
&lt;p&gt;I want a language that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is strongly typed with a powerful type system like Typescript’s but with types available at runtime for reflection.&lt;/li&gt;
&lt;li&gt;Focuses on performance&lt;/li&gt;
&lt;li&gt;Is part of a strong ecosystem with lots of existing packages&lt;/li&gt;
&lt;li&gt;Has a comprehensive standard library so we don’t have to use all &lt;a href=&quot;https://lodash.com/docs?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;these&lt;/a&gt; &lt;a href=&quot;https://underscorejs.org/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;different&lt;/a&gt; &lt;a href=&quot;https://ramdajs.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;libraries&lt;/a&gt; to do the basics&lt;/li&gt;
&lt;li&gt;Has the ability to express refined types (arrays of known length, formatted strings like emails and UUIDs)&lt;/li&gt;
&lt;li&gt;Allows you to specify dependencies’ permissions where you opt into allowing disk/network/privileged API access&lt;/li&gt;
&lt;li&gt;Has robust dependency injection support&lt;/li&gt;
&lt;li&gt;Is terse yet expressive&lt;/li&gt;
&lt;li&gt;Skips the import nonsense and makes the compiler figure it out with namespaces&lt;/li&gt;
&lt;li&gt;Can compile to efficient code (both in size over the network and runtime) to save the browser parsing time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The closest language I know of to checks the boxes I’m looking for is C#, but it’s missing a few things.  The good news is though that if this project were to ever actually get built you would need to create a language extensions to support returning the markdown language in the scripts like JSX/TSX files do. So you could also customize the language a little bit more to make it more purpose driven for this usecase which would also be a nice excuse to have the language be owned by the open source group instead of whatever corp or org the language originated from.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;For actually adding interactivity the idea is that you can set the &lt;code&gt;component&lt;/code&gt; attribute on a native component to customize its behavior or just create a new custom component which can render whatever it wants.  So in the markup example above the &lt;code&gt;section (component={someNamespace.SectionComponent}){&lt;/code&gt; line is attaching the &lt;code&gt;SectionComponent&lt;/code&gt; script to control the native &lt;code&gt;section&lt;/code&gt; component. It would be able to hook into the native components’ state and user events to only change what it needs while leaving everything else to the native implementation.  The &lt;code&gt;someNamespace.myCoolComponent&lt;/code&gt; line is a custom component.&lt;/p&gt;
&lt;p&gt;As mentioned above, I want the props (equivalent of HTML attributes) to be both strongly typed in what the component expects while also supporting any language built in type including arrays, objects and functions. There’s so much engineering that’s happened just to get over this limitation.&lt;/p&gt;
&lt;p&gt;Two way binding a la &lt;a href=&quot;https://svelte.dev/docs/svelte/bind?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;svelte&lt;/a&gt; (and many others) is such a nice quality of life feature when you need it like for getting form component values without lots of cumbersome boilerplate.&lt;/p&gt;
&lt;p&gt;Since all props are just in the DOM (whatever its evolution is), Server Side Rendering should now be easy.  The backend can just render the application in whatever state is requested and send the document with all the props set up for the scripts to initialize with.  Nothing should have to re-render when the scripts initialize until some user interaction (or network refresh) happens, and the browser can queue up user events for the scripts to process once they initialize so you never end up with those scenarios where a user clicks a button but nothing happens because the script isn’t ready yet.&lt;/p&gt;
&lt;p&gt;Without further ado, here’s a very hypothetical example of what a component script might look like&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;// Similar to parameter binding in .Net minimal APIs, the ILogger comes from the DI container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8839EF;--shiki-dark:#F286C4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DF8E1D;--shiki-light-font-style:italic;--shiki-dark:#97E1F1;--shiki-dark-font-style:inherit&quot;&gt; SectionComponent&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DF8E1D;--shiki-light-font-style:italic;--shiki-dark:#97E1F1;--shiki-dark-font-style:italic&quot;&gt;Props&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-light-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic&quot;&gt; props&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#DF8E1D;--shiki-light-font-style:italic;--shiki-dark:#97E1F1;--shiki-dark-font-style:italic&quot;&gt; ILogger&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-light-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic&quot;&gt; logger&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8839EF;--shiki-dark:#F286C4&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; views &lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#FE640B;--shiki-dark:#BF9EEE&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;  onButtonPress&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    logger&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F6F6F4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;Log&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;Button was pressed&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;    // Just assign to variables and the compiler figures out rerenders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;    views&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;  render&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-light-font-style:italic;--shiki-dark:#7B7F8B;--shiki-dark-font-style:inherit&quot;&gt;    // Return markup syntax just like TSX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8839EF;--shiki-dark:#F286C4&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;      section&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F6F6F4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;props&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;        p &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;Welcome to my site! Views: &lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F286C4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;views&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F286C4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#62E884;--shiki-dark-font-style:inherit&quot;&gt;        button&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;variant&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;secondary&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt; onPress&lt;/span&gt;&lt;span style=&quot;color:#179299;--shiki-dark:#F286C4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#4C4F69;--shiki-dark:#F6F6F4&quot;&gt;onButtonPress&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;          &quot;&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#E7EE98&quot;&gt;Press the button, Max&lt;/span&gt;&lt;span style=&quot;color:#40A02B;--shiki-dark:#DEE492&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7C7F93;--shiki-dark:#F6F6F4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;comprehensive-components--standard-library&quot;&gt;Comprehensive Components &amp;#x26; Standard Library&lt;a class=&quot;anchor&quot; href=&quot;#comprehensive-components--standard-library&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A sizeable part of this whole idea is around having an awesome fully featured component library.  It bugs me how inflexible and lacking native HTML elements are which means everyone ends up building their own which end up usually missing some functionality and makes everyone’s user experience inconsistent. As a perfect example of how terrible some native components are, let me remind you what the native multi-select component looks like:&lt;/p&gt;
&lt;select multiple class=&quot;dark:bg-gray-800 dark:text-white&quot;&gt;
  &lt;option value=&quot;Apples&quot;&gt;Apples&lt;/option&gt;
  &lt;option value=&quot;Bananas&quot;&gt;Bananas&lt;/option&gt;
  &lt;option value=&quot;Oranges&quot;&gt;Oranges&lt;/option&gt;
  &lt;option value=&quot;Pears&quot;&gt;Pears&lt;/option&gt;
  &lt;option value=&quot;Strawberries&quot;&gt;Strawberries&lt;/option&gt;
&lt;/select&gt;
&lt;p&gt;I dare you to coach anyone non tech savvy over 50 years old how to use this.&lt;/p&gt;
&lt;p&gt;As a grab bag, here’s my wish list of components that would be nice to stop building over and over and over again:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Forms that actually handle real world usage with dependent state handling, dependent field validation, multi step workflows, and strongly typed values returned&lt;/li&gt;
&lt;li&gt;Form Inputs that handle icons, units, and formatting&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Number inputs that actually result in your script getting a number&lt;/del&gt; (just learned about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/valueAsNumber?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;valueAsNumber&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Non sucky multi select, that includes variations in styling for tag style, count style, text style&lt;/li&gt;
&lt;li&gt;Combobox / async selection search&lt;/li&gt;
&lt;li&gt;Checkboxes with a variant to render as a toggle&lt;/li&gt;
&lt;li&gt;Tooltips&lt;/li&gt;
&lt;li&gt;Dialogs&lt;/li&gt;
&lt;li&gt;Carousels&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://component.gallery/components/drawer/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Drawers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Toast messages&lt;/li&gt;
&lt;li&gt;Graphs &amp;#x26; Charts&lt;/li&gt;
&lt;li&gt;Tabs&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://component.gallery/components/rich-text-editor/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Rich text editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Calendar&lt;/li&gt;
&lt;li&gt;Expandable Tree view&lt;/li&gt;
&lt;li&gt;Mosaic image layout&lt;/li&gt;
&lt;li&gt;Tables that can handle sorting, filtering, pagination, resizable columns, selections, inline editing, expandable rows, empty states, and the whole kitchen sink&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/patterns/layout/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Standard layout components&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the framework would be open source you would not only be able to fix bugs and add components everyone wants, but also dive deep and see the implementation of native components and how they’re composed from primitives when you need to customize them.&lt;/p&gt;
&lt;p&gt;Another benefit of having the standard component library be so full featured (and therefore heavily used) is that accessibility tools (screen readers/voice input/AI) can build out specialized functionality for each of them and not have to worry as much about everyone’s special snowflake components that forgot about a11y. Keyboard users also rejoice.&lt;/p&gt;
&lt;h2 id=&quot;authentication&quot;&gt;Authentication&lt;a class=&quot;anchor&quot; href=&quot;#authentication&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another easy layup for the evolution of the web is fixing the nightmare that is authentication as we know it today. How many logins do you have stored in your password manager? I have 636. And many of those sites have asinine password requirements that make them less secure and more annoying to use.  Even more have already stored your credentials insecurely and been hacked.  I, just like everyone else, am usually too lazy to go and update my password whenever they have a breach.&lt;/p&gt;
&lt;p&gt;How about we have the browser manage your login(s) and then have APIs for the sites/apps to authenticate and get access to the profile info you want to share?  Even 2FA could be managed by the browser login system so every site wouldn’t have to build (or buy) their own system.  Each app could specify the maximum staleness of the authentication token to require you to log in again for critical operations.&lt;/p&gt;
&lt;p&gt;Wouldn’t it be nice to log into pretty much everything at once?&lt;/p&gt;
&lt;h2 id=&quot;backend&quot;&gt;Backend&lt;a class=&quot;anchor&quot; href=&quot;#backend&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Photo by &amp;lt;a href=&amp;quot;https://unsplash.com/@tvick?utm_source=unsplash&amp;amp;#x26;utm_medium=referral&amp;amp;#x26;utm_content=creditCopyText&amp;quot;&amp;gt;Taylor Vick&amp;lt;/a&amp;gt; on &amp;lt;a href=&amp;quot;https://unsplash.com/photos/cable-network-M5tzZtFCOfs?utm_source=unsplash&amp;amp;#x26;utm_medium=referral&amp;amp;#x26;utm_content=creditCopyText&amp;quot;&amp;gt;Unsplash&amp;lt;/a&amp;gt;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3956&quot; height=&quot;2220&quot; src=&quot;/_astro/taylor-vick-server-rack.C_sPhWEo_Z1mT0qz.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I’m not going to go into as much detail on the backend, first because this post is already way longer (and has taken way more time) than I expected, but also because backends are necessarily quite varied in what they need to do and the systems they need to talk to. I wouldn’t expect everyone’s backends to behave as similarly as my envisioned frontend, but there are a number of things that come to mind that would be nice to have…&lt;/p&gt;
&lt;h3 id=&quot;shared-resource-typing-and-functionality&quot;&gt;Shared Resource Typing and Functionality&lt;a class=&quot;anchor&quot; href=&quot;#shared-resource-typing-and-functionality&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The backend would be in the same language as the frontend. Obviously… It’s such a team efficiency boost to write everything in the same language so you don’t have to context switch your brain when hopping between frontend and backend, not to mention all the benefits of shared tooling and utilities.  The web has already been marching in this direction with Node, Next.js and React server components of course but it’s worth it to restate how nice it is to be able to share code between the backend and the frontend (with a proper project structure set up to know what code is shared vs exclusive) especially for things like validation which need to happen on both sides anyways.&lt;/p&gt;
&lt;p&gt;But this section is really about how great it would be if all projects (not just the ones that dedicate a ton of time to make this happen) had a tight integration between frontend and backend for synchronizing data organized into resources. Resources come in all shapes and sizes, backed by many different data stores, that result in many different capabilities the resource can provide.  With that in mind it should be easy to define in your api per resource: if pagination is supported; which fields are sortable; which fields are immutable; which fields are only mutable at creation time or update time; and which fields are deprecated.&lt;/p&gt;
&lt;p&gt;As that resource schema definition changes during development the client should be hooked up with automatic type generation to the changes so all the functions that interface with the API have the updated signatures and you can see type errors where changes need to be made to accommodate the API.&lt;/p&gt;
&lt;h3 id=&quot;data-synchronization&quot;&gt;Data Synchronization&lt;a class=&quot;anchor&quot; href=&quot;#data-synchronization&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The obvious next question though is how do you synchronize data between client and server. Do we use REST or GraphQL or gRPC or something else? Let me dodge that question for a sec and take a step back to think about things from first principles.&lt;/p&gt;
&lt;p&gt;The data (resources) we want to store can always be represented as an array of objects, even if the array is just has a single item or the object has a single property. And those objects/resources often relate to each other so it makes sense to me that we should be leaning on a relational database to manage the data.  On the backend there can be good reasons why you might choose not to use a relational database but they pretty much come down to data size and I/O performance.  However, with the size of data clients should be dealing with I can’t see any reason not to use a relational data model for client application state that’s synchronized with the server (there would still be component level state in script variables).&lt;/p&gt;
&lt;p&gt;So in the easiest case of a 100% offline app, state management would just look like updates to table rows.  There of course already is &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IndexedDB&lt;/a&gt; available in browsers but &lt;a href=&quot;https://jlongster.com/future-sql-web?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;apparently this is slow&lt;/a&gt; so I would like to see something more akin to sqlite wrapped in the browser with the table schema’s defined by the API resources plus any extra client-side only tables that are needed.&lt;/p&gt;
&lt;p&gt;With that established, then the question becomes how do you seed the data on initial page load, and how do you keep the slice of data the client cares about (and is allowed to see) in sync with the backend.  &lt;strong&gt;For initializing&lt;/strong&gt;, we would need a new kind of resource request for an efficiently serialized and compressed database file that would be loaded (upserted by default) into the clients database as the page and scripts load. That database would be customized by the server to contain all the data the client needs across linked resources so no waterfall of network requests need to be made when a page loads.  It would still need to be requested via URL so the contents could be customized (and cached) as needed per page, and there would also need to be a mechanism for the clients to only request it when their local database is empty or too stale.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1589591854/macro-mania/DSC09886.jpg&quot; alt=&quot;Bubbles from &lt;a href=&amp;#x22;/photos/macro&amp;#x22;&gt;Macro Mania&lt;/a&gt;&quot; title=&quot;Bubbles from &lt;a href=&amp;#x22;/photos/macro&amp;#x22;&gt;Macro Mania&lt;/a&gt;&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1589591854/macro-mania/DSC09886.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For reading data&lt;/strong&gt; (get one or get many of a resource) my ideal would be a request similar to how REST works today but with more strictly defined and enforced patterns for filtering, paging, metadata, and fetching related resources. Currently, REST is great for simplicity and ease of implementation but is way too lax in standardization which results in everyone implementing it differently. GraphQL is great for fetching related resources and having better standardization around paging and metadata but from my experience usually ends up as a headache to implement on the backend (securely and performantly) and the frontend ends up with an explosion of types as every component is trying to fetch things a little differently which is such a pain for shared utility methods. I think the pragmatic compromise is a protocol that has well defined patterns for fetching the slice of a resource you care about along with the related resources you want which the server can figure out the most efficient way to query and bundle up in a single request and response. The client could then upsert responses directly into the local database for components to re-render with.  The client could also specify in its table schemas if it would like to receive automatic updates either via polling or a persistent web socket for push.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For data mutations&lt;/strong&gt; originating on the client, it would look the same as in the offline app case where you would update the corresponding table row so the client can optimistically render, but then the changes would get batched by resource and uploaded to the server which would then respond with the full resource data including any server generated fields which the client would update its db with. The resource schema definition shared with the client would provide strong typing around which fields can be modified (or created with new records).  There would also need to be strong error handling around failed or partial updates.&lt;/p&gt;
&lt;h2 id=&quot;isnt-this-like&quot;&gt;Isn’t this like…?&lt;a class=&quot;anchor&quot; href=&quot;#isnt-this-like&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All my dreaming might have sparked some associations to go off in your head with other technologies you’ve used that do a certain piece similarly.  As far as I know and have been able to research there’s nothing that comes close to the full picture I’m laying out here. If there is, please let me know!  With that said, here’s a couple of the technologies that come to mind as closest with my impression of what they’re missing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web components&lt;/strong&gt; — have similarities with the custom elements with behavior I talk about in the scripting section, but obviously don’t address any of the other things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rails&lt;/strong&gt; — The &lt;a href=&quot;https://rubyonrails.org/doctrine?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;doctrine&lt;/a&gt; is an amusing read. I agree with most of the points like Optimize for programmer happiness and Convention over Configuration, but I don’t think they should come at the expensive of performance which lands you in &lt;a href=&quot;https://www.techempower.com/benchmarks/#section=data-r23?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;#396th place out of 510&lt;/a&gt; in performance benchmarks. Even if you were to take the performance of the #50 spot in comparison, you’d need 14 times more horsepower/servers/spend in comparison.  While some of the philosophy is similar, my proposal here is also more broad in scope of course instead of what Rails can do is inherently limited to with the current web so it can’t have a shared syntax across server/styles/scripts/markup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blazor&lt;/strong&gt; — I hadn’t really looked that closely at Blazor before writing/researching this post but there’s definitely some similarities.  They are obviously still bound by the restrictions of the current stack (like having all string attributes) and also ship a ton of code to the browser which results in &lt;a href=&quot;https://krausest.github.io/js-framework-benchmark/2025/table_chrome_140.0.7339.81.html?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;horrible frontend performance&lt;/a&gt;.  Some of that could be improved by having the browser take on more responsibility but someone who knows more about it than I can weigh in on why they’re so heavy and slow.  Even with those issues fixed, the most important part of this whole idea is that it needs to be a new open source standard not controlled by any one company trying to lock you in only to dump you when their objectives change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Electron &amp;#x26; alternatives&lt;/strong&gt; — There’s a lot of different &lt;a href=&quot;https://github.com/sudhakar3697/awesome-electron-alternatives?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Electron alternatives&lt;/a&gt; out there that share some ideas with what I’ve laid out. But of course they’re all aimed at desktop apps, not a wholistic solution that encompasses everything from a static web document to an interactive web apps to a packaged offline desktop app. They’re not build for splitting the app into pages or chunks and require you to install the whole app. Plus, most of the ones that aren’t just wrappers on top of existing web tech look like they’d completely fall flat building complex UI’s and apps with themes. &lt;a href=&quot;https://github.com/Elanis/web-to-desktop-framework-comparison?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Here’s another comparison between them I found&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;will-this-ever-get-built&quot;&gt;Will this ever get built?&lt;a class=&quot;anchor&quot; href=&quot;#will-this-ever-get-built&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Probably not. But maybe! I certainly don’t have the time, do you?&lt;/p&gt;
&lt;p&gt;There’s a thousand other things I’d change along the way if I were the one building this, even some of the initial ideas in this post I’m sure will fall apart when it comes to feeling the developer experience actually building an app in the new platform.  The best ideas come from iteration experimentation and refinement.&lt;/p&gt;
&lt;p&gt;I’m sure you don’t agree with all my ideas but I hope this gets you thinking about what your pie in the sky web dev stack would look like every time you have to re-invent the wheel.&lt;/p&gt;
&lt;p&gt;Lemme know your ideas in the comments!&lt;/p&gt;</content:encoded></item><item><title>Passion Over Profits</title><link>https://dillonshook.com/passion-over-profits/</link><guid isPermaLink="true">https://dillonshook.com/passion-over-profits/</guid><pubDate>Thu, 14 Aug 2025 00:48:28 GMT</pubDate><content:encoded>&lt;p&gt;I’m a little over 4 months into the new job and I think now it’s safe to talk about a topic that’s been fermenting in my head without risk of jinxing anything at this point.&lt;/p&gt;
&lt;p&gt;This last time around finding a new job was the first time in the 15 years of my career where multiple offers have actually lined up in spacetime such that I had to decide between them.  I’m sure I could have made this happen before if that was the goal but I’ve always tried to be selective with the companies I apply to.  As everyone has already told you I’m sure, this is a great position to be in when negotiating your offer.&lt;/p&gt;
&lt;p&gt;After a few back and forths with each company I felt pretty good about what each was offering, but on paper one was pretty stacked&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Offer 1&lt;/th&gt;&lt;th&gt;Offer 2&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Salary&lt;/td&gt;&lt;td&gt;Baseline&lt;/td&gt;&lt;td&gt;Baseline plus even more than a minimum wage salary&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Equity&lt;/td&gt;&lt;td&gt;Some shares, but no near term timeline for any value&lt;/td&gt;&lt;td&gt;Strong chance the company will go public within the year and result in a 100k payout&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Bonus&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;td&gt;5-10% Annual bonus&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Title&lt;/td&gt;&lt;td&gt;Senior Engineer&lt;/td&gt;&lt;td&gt;Staff Engineer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Commute&lt;/td&gt;&lt;td&gt;Hybrid&lt;/td&gt;&lt;td&gt;Fully Remote&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Team&lt;/td&gt;&lt;td&gt;Solid group of really smart engineers&lt;/td&gt;&lt;td&gt;Working on “the best dev team the company has”&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;And to top it all off, Offer 2 had company offsite coming up I’d be invited to in the Bahamas!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1638657901/costa-rica/DSC05141.jpg&quot; alt=&quot;Actually Costa Rica, but this is what I imagined&quot; title=&quot;Actually Costa Rica, but this is what I imagined&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1638657901/costa-rica/DSC05141.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;&gt;&lt;/p&gt;
&lt;p&gt;Just looking at them side by side, Offer 2 won on pretty much every aspect you can think of.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But I still ended up turning it down.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There was one thing I was missing from Offer 2 and had in abundance for Offer 1: &lt;strong&gt;Passion&lt;/strong&gt;.  As you might know from my other post, Offer 1 was &lt;a href=&quot;https://cfs.energy?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Commonwealth Fusion Systems&lt;/a&gt; where I get to work with insanely talented and smart people pushing the frontier of science to try and accomplish something humanity has never done before. I’m so much more passionate about working on futuristic tech solutions to climate change than the normal sort of business that Offer 2 would have me work on.  After a certain point, mo’ money don’t mean mo’ happiness. So to think of it another way, by turning down the extra money I effectively bought happiness with money that wouldn’t have made me happier.&lt;/p&gt;
&lt;p&gt;A long time ago I read some career advice (probably from some random reddit post) that boiled down to the fact that job satisfaction comes down to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Pay&lt;/li&gt;
&lt;li&gt;The Work&lt;/li&gt;
&lt;li&gt;The People&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you only like 1 (or even worse, 0!) of the 3 you should be spending all your free time looking for a new job or advancing your skills so you can get a better job. If you have 2 you should be casually looking for new opportunities, and if you have all 3, hold on tight!  It’s obvious enough, but if the pay sucks the rest of your life suffers. If you can’t stand the people you work with you’re gonna end up miserable, and if you find the work tedious and boring you’re going to spend a huge chunk of your life checked out and bored.  Each one of these is a spectrum of course, and being passionate about your job is just the strongest version of liking the work you do.&lt;/p&gt;
&lt;p&gt;I feel incredibly grateful that I not only had the chance to pick between two great outcomes, but also that I was able to land a dream job I’m passionate for.  I hope some day you’ll get the chance to pick too, and &lt;strong&gt;choose your passion!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
P.S.  More comments posted over on &lt;a href=&quot;https://news.ycombinator.com/item?id=44900084&amp;#x26;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hacker News&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Launching is the Second Hardest Part</title><link>https://dillonshook.com/launching-is-the-second-hardest-part/</link><guid isPermaLink="true">https://dillonshook.com/launching-is-the-second-hardest-part/</guid><pubDate>Mon, 19 May 2025 11:44:47 GMT</pubDate><content:encoded>&lt;p&gt;If &lt;a href=&quot;/starting-is-the-hardest-part&quot;&gt;Starting is the Hardest Part&lt;/a&gt; then surely launching is the second hardest part. And I don’t mean it’s not as hard as starting, it’s just the second time you’ll be facing the hardest part of getting a product off the ground.  Just like the first 80% is the hardest, the second 80% of the work is what drags, and the third 80% is really what gets you…&lt;/p&gt;
&lt;p&gt;But it’s a big moment when you get there!&lt;/p&gt;
&lt;a href=&quot;https://catsearch.net/&quot; target=&quot;_blank&quot; class=&quot;no-styling&quot;&gt;&lt;img class=&quot;no-zoom&quot; alt=&quot;Cat Search Site&quot; src=&quot;/_astro/cat-search-site.Z-iiWtxT.png&quot;/&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href=&quot;https://catsearch.net/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cat Search&lt;/a&gt; beta is finally alive and working!&lt;/p&gt;
&lt;p&gt;But wow… it took longer that I thought to get there even for such a small project so let me talk you through some of the challenges.&lt;/p&gt;
&lt;h2 id=&quot;the-known&quot;&gt;The Known&lt;a class=&quot;anchor&quot; href=&quot;#the-known&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Starting with all the stuff I knew about above my MVP release line, there were lots of small details to wrap up like setting up backend monitoring (I went with &lt;a href=&quot;https://www.honeycomb.io/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Honeycomb&lt;/a&gt;) and reporting any errors from the frontend through a new API so I can see if there are any problems affecting the users.  There were also last minute bugs to fix like the one where I discovered the Google tablet markup is significantly different than the desktop layout and broke all my selectors.&lt;/p&gt;
&lt;p&gt;Then there was getting the email verification set up and working so my API wouldn’t be wide open to abuse.  I went with &lt;a href=&quot;https://resend.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;resend&lt;/a&gt; and got stuck on verifying the domain for 2 days waiting for DNS to propagate before realizing there was a copy pasta mistake…&lt;/p&gt;
&lt;p&gt;And of course I needed to make a website which is like starting a whole new project in itself with all the decisions to make on tech stacks all over again.  I stuck with &lt;a href=&quot;https://astro.build/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;the familiar&lt;/a&gt; though used a new site template which takes some time to learn.  But to make a product website you need to first do things like choose fonts, colors, and a logo, which all require you to think about the nebulous concept that is brand identity.&lt;/p&gt;
&lt;p&gt;Coming up with a logo was challenging in itself to find something representative.  I spent hours looking for inspiration and then trying some AI tools (I promise I’ll pay an artist to make a better version if this thing ever makes money) before coming up with something half way decent.  Then I spent many more hours more converting it to SVG, cleaning up the paths, optimizing it so it’s not a 2MB SVG, and then creating various downsized versions.  Even as I’m writing this now and looking at the site I’m getting sidetracked looking at the favicon version and going to tweak it.&lt;/p&gt;
&lt;p&gt;It goes without saying that in order for anyone else to see what you’ve made you actually have to deploy it somewhere. And in order to not cause more work for yourself when you change things you need to get build and deploy automation set up.  My first approach was to build it alongside the API and have ASP.NET serve it up as static files just so I’d only have one build artifact and thing to deploy.  I got that all set up and working but there were some issues with the DNS setup where Route66 requires you to use a CNAME record which doesn’t allow you to omit the “www” subdomain and also messes with the email DNS setup.  After messing with that a bit I just pivoted to using the same setup as this site and host the API separately so I can use an A record.&lt;/p&gt;
&lt;h2 id=&quot;the-unknown&quot;&gt;The Unknown&lt;a class=&quot;anchor&quot; href=&quot;#the-unknown&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After doing all that different stuff I was feeling pretty good and ready to tackle the unknown part of publishing to the Chrome and Firefox extension “web stores” which I’d never done before.  I had done a similar “submit lots of different promotional images in very specific resolutions” dance when publishing &lt;a href=&quot;https://macrocosm-game.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Macrocosm&lt;/a&gt; to the app store but it’s just one more step that eats time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/chrome-image-requirements.8qszbQ76_mDPbg.webp&quot; alt=&quot;Chrome extension image requirements&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1091&quot; height=&quot;790&quot;&gt;&lt;/p&gt;
&lt;p&gt;After you submit the extension you have to wait a day or two for some review process to approve it and let the extension be published and visible to download.  Seeing what you’ve made alongside all the other extensions is a good feeling, but that feeling was taken away when I installed it and everything just… &lt;strong&gt;failed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Almost as disparaging as the fact that local development is working fine and prod is completely busted is the fact that I’m also getting different errors between Chrome and Firefox.&lt;/p&gt;
&lt;p&gt;The first problem to tackle was that Chrome was throwing errors that the methods off the &lt;code&gt;browser&lt;/code&gt; object exposed to extensions were undefined.  It was news to me that &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#javascript_apis?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Chrome doesn’t support that&lt;/a&gt; because the &lt;a href=&quot;https://extension.js.org/docs/features/multi-platform-builds#polyfill-support?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;framework I’m using to develop the extension&lt;/a&gt; seemingly automatically polyfills it during local development but requires a command line argument to build with the polyfill included. Sigh…&lt;/p&gt;
&lt;p&gt;The next (and biggest) problem was all my API calls were failing with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CSP&lt;/a&gt; errors.  To make matters that much more challenging to debug, both Google and DuckDuckGo are throwing their own CSP errors like&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Content-Security-Policy: The page’s settings blocked an event handler (script-src-attr) from being executed because it violates the following directive: “script-src &amp;#39;nonce--zpqhE9NZPHdP41-FRX-Xw&amp;#39; &amp;#39;strict-dynamic&amp;#39; &amp;#39;report-sample&amp;#39; &amp;#39;unsafe-eval&amp;#39; &amp;#39;unsafe-inline&amp;#39; https: http:” Source: _rtf(this)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;on Google, and this one on DDG:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Content-Security-Policy: The page’s settings blocked the loading of a resource (default-src) at https://duckduckgo.com/dist/wpm.1619.ea48354a2359f567744b.js because it violates the following directive: “default-src &amp;#39;none&amp;#39;”&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After confirming the issue was different in prod vs. local because I was hitting localhost for my API while developing it which is apparently exempt from CSP.  As I started researching ways to get around this the sense of dread crept in that this would be a total show stopper and all my work would be for naught.  Finding out what is and isn’t allowed with CSP &lt;em&gt;for extensions&lt;/em&gt; is pretty challenging, and the &lt;a href=&quot;https://github.com/mdn/content/issues/39168?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN documentation is even contradictory on the matter&lt;/a&gt; which adds to the fun.  After a few dead ends messing with the permissions and &lt;code&gt;host_permissions&lt;/code&gt; in the extension manifest I found that the actual way around it is to set up a background script, then use &lt;code&gt;browser.runtime.sendMessage&lt;/code&gt; and &lt;code&gt;browser.runtime.onMessage.addListener&lt;/code&gt; to make the API calls in the background script and pass the data back and forth.&lt;/p&gt;
&lt;p&gt;That didn’t sound so bad at first other than a bunch more boilerplate to strongly type the parameters and return types but it turns out this is a super annoying function to work with because &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;the responses automatically get wrapped in a promise&lt;/a&gt; so you can’t use async/await inside of it.  I need to await getting the user credentials out of extension storage before making the API call and then also pass errors back to the extension which the signup flow relies on.  I feel dumb saying this but it took me 6 or 7 tries publishing new versions to actually get this working right. I kept thinking it was all working only to discover something was broken in the other browser or another edge case of error handling didn’t work.  This was extremely demotivating to feel suck going back and forth so many times with this one function that I feel like shouldn’t even need to exist.  How exactly does it add security to make your API calls in a background script instead of directly from the content script? Why wouldn’t an allow list of domains the extension can talk to be sufficient?&lt;/p&gt;
&lt;p&gt;The last major problem was all the custom fonts I included fail to load in the prod build, once again due to CSP restrictions.  There’s limited info on this problem as well but the only reasonable solution seems to be to inline the fonts as base64 data.  Another rabbit hole to step into, yay.  I try a whole bunch of different things but none work and &lt;a href=&quot;https://github.com/extension-js/extension.js/issues/264?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;the best I can do is open an issue&lt;/a&gt; and give up on custom fonts for now.&lt;/p&gt;
&lt;p&gt;Another kicker to debugging all these problems is that browser inspectors are of course different between Chrome and Firefox, you can’t install arbitrary extensions in Firefox and instead need the separate Firefox Developer Edition installed, and in Chrome there doesn’t seem to be any way to get the full inspector open for a background script so you’re left trying to interpret crappy browser error messages like &lt;code&gt;Error: Could not establish connection. Receiving end does not exist&lt;/code&gt;.  I also ran into issues where the exact same build behaved differently between Firefox Developer Edition installed temporarily and the published version installed in my normal Firefox. But going into the debugging menu and opening the inspector somehow fixed it!?!  There was also a time where after using a newly installed version for 10 minutes or so in Firefox it stopped working and I discover it somehow spontaneously uninstalled the extension!?!?!? ARRRRGH&lt;/p&gt;
&lt;p&gt;It’s a bad vibe to feel like you’re building on shifting sand and I don’t yet know how I can add integration or end to end tests that would give me confidence in catching all the differences between browsers and build artifacts.&lt;/p&gt;
&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;a class=&quot;anchor&quot; href=&quot;#the-takeaway&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If it was easy everyone would be doing it I suppose.  So persistence is key, even when life also “gets in the way”, or, to put it better, just takes precedence over a side project.&lt;/p&gt;
&lt;p&gt;Plan for the known, but also plan for the fact that there will be unknowns that could take more time than the known’s when launching on any new platform.  It’s also important to de-risk your project ASAP for any showstopper technical issues.  It’s easy to think you’ve done that with your local development setup but &lt;strong&gt;if your production environment looks pretty different then you really haven’t&lt;/strong&gt;, so test your prod environment sooner rather than later.  I learned this lesson on &lt;a href=&quot;https://macrocosm-game.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Macrocosm&lt;/a&gt; with challenges in the prod build on the app store, but it was a mistake to think it wouldn’t be as big of an issue this time.&lt;/p&gt;
&lt;p&gt;And of course, if you’ve been falling out of love with your search results I’d love it if you’d &lt;a href=&quot;https://catsearch.net?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;give Cat Search a whirl&lt;/a&gt; and let me know what you think!  It’s definitely in beta state and there’s a long list of stuff I want to improve or add already of course but hearing real feedback is more important than jumping right into that.  The feedback button is in the top right when using it.&lt;/p&gt;</content:encoded></item><item><title>5 Tips for Starting a New Job</title><link>https://dillonshook.com/starting-a-new-job/</link><guid isPermaLink="true">https://dillonshook.com/starting-a-new-job/</guid><pubDate>Fri, 04 Apr 2025 02:50:22 GMT</pubDate><content:encoded>&lt;p&gt;I just started a new job this week I’m super pumped about at &lt;a href=&quot;https://cfs.energy?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Commonwealth Fusion Systems&lt;/a&gt;! The first day was a whirlwind of learning new things and asking all the questions just like it has been every other time I’ve started a new job. But this time was a little different, and not just because this is the first time in 5 years I’m going back into an office.  This time the questions involved things you totally deal with every day like superconducting magnets, cryogenic temperatures, supercritical helium, and 50,000 amp currents.  Luckily I don’t have to fully understand all those things to do my job but it’s always good to understand where you fit in at a new job and how the whole process works at a high level.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;CFS Toroidal Field Case&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1600&quot; height=&quot;900&quot; src=&quot;/_astro/cfs.QGlsbwH-_1Xx8vn.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Today I wanted to talk about the top 5 things I always try to do when starting a new job outside the routine “watch the training videos, set up your machine, get the code running, open your first ticket” instructions that come with every new software job.  Writing these down is a good way for me to not only organize my own thoughts but also think critically about them and set some goals for myself.  Hopefully when it comes time for your next role these will be helpful for you too!&lt;/p&gt;
&lt;h2 id=&quot;1-build-relationships&quot;&gt;1. Build Relationships&lt;a class=&quot;anchor&quot; href=&quot;#1-build-relationships&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I &lt;a href=&quot;/work-on-side-projects/&quot;&gt;mentioned before&lt;/a&gt;, building your relationships and network is the best thing you can do in your career in my opinion.  And that’s not at all just for the benefits after you leave a company.  Knowing the right people to talk to and having a good relationship so they want to help you out as much as possible is crucial for being successful at your job.  These are the people who you’ll be turning to for help, helping in return, asking for their time, and more importantly, advocating for you when it comes time for a promotion. Meet as many people as you can, exploring your way through the branches on the org tree and really get to know the people, not just the employee.&lt;/p&gt;
&lt;h2 id=&quot;2-build-your-context&quot;&gt;2. Build your Context&lt;a class=&quot;anchor&quot; href=&quot;#2-build-your-context&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the differentiating factors (&lt;em&gt;for now&lt;/em&gt;) between human software engineers and AI is the ability to effectively build all the context you need to work on a codebase optimally.  AI is obviously getting better and better at slurping up and sending large chunks of code as context if you let it, but what you need to build goes beyond that.  You do need to start with the current state of the codebase, what the patterns, norms, libraries used, and immediate problems are. But, more importantly, you need to learn how the software solves the human problems it exists for in the first place.  What are the current limitations? What features are being used now? What’s being asked for? Plug into the product leader mindset.&lt;/p&gt;
&lt;p&gt;This one takes the longest out of all the points, and arguably just keeps on going, but the goal should be to start triaging which context is most important to learn first and become effective as soon as possible.  There’s no shortcut to this one, just read lots of code, docs, PRs, and ask lots of questions.&lt;/p&gt;
&lt;h2 id=&quot;3-keep-a-list&quot;&gt;3. Keep a List&lt;a class=&quot;anchor&quot; href=&quot;#3-keep-a-list&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1557802939/boston/DSC05681.jpg&quot; alt=&quot;What secrets lie within?&quot; title=&quot;What secrets lie within?&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1557802939/boston/DSC05681.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1557802939/boston/DSC05681.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1557802939/boston/DSC05681.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1557802939/boston/DSC05681.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1557802939/boston/DSC05681.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1557802939/boston/DSC05681.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you’re building your context in #2 by reading through the code and diving into using the product really, you’ll inevitably have questions about how something works, or why X, Y, &amp;#x26; Z are done that way, or even ideas for new features.  Get in the habit of writing them all down on a list somewhere.  As you get answers either on your own or by asking a coworker check them off (and write down the answer if you think you’ll forget in the beginning info overload).  This is not only to keep organized and remind you to ask the questions, but also there will inevitably be some questions that don’t get answered right away that are still good to keep track of. Come back to your list after a month or so and first (hopefully) be impressed by how far you’ve come with your understanding and then see if there are any open questions you need answers to or features that you still thing make sense.&lt;/p&gt;
&lt;p&gt;You only get the fresh eyes of a new user of the product once.  After you’ve been working on the same thing for a week (let alone, months or years) you become blind to all sorts of confusing behavior and bad UI as your muscle memory builds.  By being the new (very attentive!) user yourself and writing down all the stumbling blocks, bugs, and frustrations you can really help out the product team by sharing your findings and hopefully be a part of fixing the issues that real users will also be facing.&lt;/p&gt;
&lt;p&gt;My advice is to also keep any really large feature or refactoring work you notice to yourself and on the list for the first month.  You really just don’t have enough context yet to know if those things make sense to do yet (or ever) and if you come out of the gate swinging with all these drastic changes you’re just going to give a bad impression and look like you don’t know what you’re talking about, because you probably don’t yet. But if after waiting a month you still think they make sense, bring them up with your manager and see what they think.&lt;/p&gt;
&lt;h2 id=&quot;4-improve-onboarding--documentation&quot;&gt;4. Improve Onboarding &amp;#x26; Documentation&lt;a class=&quot;anchor&quot; href=&quot;#4-improve-onboarding--documentation&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This should be a bit of a no-brainer but the easiest first task and PR is to update the README and documentation for setting up the repo and local development environment.  That section is the most likely to get out of date and break since it’s run so infrequently and usually dependent on other machine setup steps happening in the right order.  If the whole thing works flawlessly the first try with no one coaching you through it be sure to personally thank the last person who touched that section of the README.  I can count on one finger the times that’s happened for me :)&lt;/p&gt;
&lt;p&gt;Part of #2 should also be looking for up to date architecture diagrams.  These are also a rare commodity since they so often don’t get updated as the architecture changes.  An early value add for the company you can do is to take it upon yourself to update the diagrams while pairing with someone who knows the architecture well.  This helps you learn and helps the next person that needs to reference them.&lt;/p&gt;
&lt;h2 id=&quot;5-document-the-tlas&quot;&gt;5. Document the TLA’s&lt;a class=&quot;anchor&quot; href=&quot;#5-document-the-tlas&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You obviously should know that a TLA is a three letter acronym 😉. Every company has tons of industry and domain specific jargon that is also gonna take some time to wrap your head around.  If you’re lucky someone will have already set up a glossary page that defines the commonly used ones.  But just like architecture diagrams they’re often incomplete, or the definitions need further explanation.  Once again, take it upon yourself to help the whole company out and improve (or create) the glossary for the next person as you discover the meanings to the FLAS.&lt;/p&gt;
&lt;h2 id=&quot;finally&quot;&gt;Finally&lt;a class=&quot;anchor&quot; href=&quot;#finally&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This will be the 8th company I’ve worked for in my career which is a little wild to think about.  Maybe you’ve also been around the block a few times these tips are old news to you. If that’s the case, help us all out and leave a comment with your favorite tips!&lt;/p&gt;
&lt;p&gt;A good first impression goes a long ways so do your absolute best in the beginning and it will pay off.  Hope your next new job experience is great too!&lt;/p&gt;</content:encoded></item><item><title>Surprisingly Cheap and Powerful Server Hosting for Indie Devs in 2025</title><link>https://dillonshook.com/postgres-cloud-benchmarks-for-indie-devs/</link><guid isPermaLink="true">https://dillonshook.com/postgres-cloud-benchmarks-for-indie-devs/</guid><description>I benchmarked 7 server hosts to find the best performance per dollar</description><pubDate>Fri, 21 Mar 2025 19:28:35 GMT</pubDate><content:encoded>&lt;p&gt;I started looking for a place to host Cat Search and of course instead of doing things the easy way and just deploying it to one place I had to do things the hard way and test all my options to see what the best option for me was.&lt;/p&gt;
&lt;p&gt;My goals for hosting are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid vendor lock in&lt;/li&gt;
&lt;li&gt;Get the best bang for the buck&lt;/li&gt;
&lt;li&gt;Stay under or around $15 per month&lt;/li&gt;
&lt;li&gt;Meet performance requirements (looking for at least sub 100ms response times under load)&lt;/li&gt;
&lt;li&gt;Have relatively easy ways to manage and monitor the servers&lt;/li&gt;
&lt;li&gt;Automatic deploys on push&lt;/li&gt;
&lt;li&gt;Database backups&lt;/li&gt;
&lt;li&gt;Ability to scale up and out in the future&lt;/li&gt;
&lt;li&gt;A good user experience&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are of course over 9,000 ways to host a site and API these days but I’m looking to keep it as simple as possible to start with and try to avoid as much custom work as possible to be able to focus on the product, but all while keeping costs low to try to make this a profitable venture as soon as possible.&lt;/p&gt;
&lt;p&gt;The architecture of the backend I’m deploying is quite simple, here it is:&lt;/p&gt;
&lt;div class=&quot;flex items-center justify-center&quot;&gt;&lt;svg id=&quot;mermaid-0&quot; width=&quot;100%&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; style=&quot;max-width:450.6865539550781px&quot; viewBox=&quot;-180.34327697753906 -65.5 450.6865539550781 262&quot; role=&quot;graphics-document document&quot; aria-roledescription=&quot;architecture&quot;&gt;&lt;style&gt;#mermaid-0{font-family:arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-0 .error-icon{fill:#552222;}#mermaid-0 .error-text{fill:#552222;stroke:#552222;}#mermaid-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-0 .marker{fill:#333333;stroke:#333333;}#mermaid-0 .marker.cross{stroke:#333333;}#mermaid-0 svg{font-family:arial,sans-serif;font-size:16px;}#mermaid-0 p{margin:0;}#mermaid-0 .edge{stroke-width:3;stroke:#333333;fill:none;}#mermaid-0 .arrow{fill:#333333;}#mermaid-0 .node-bkg{fill:none;stroke:hsl(240, 60%, 86.2745098039%);stroke-width:2px;stroke-dasharray:8;}#mermaid-0 .node-icon-text{display:flex;align-items:center;}#mermaid-0 .node-icon-text&gt;div{color:#fff;margin:1px;height:fit-content;text-align:center;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;}#mermaid-0 :root{--mermaid-font-family:arial,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;/g&gt;&lt;g class=&quot;architecture-edges&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 102.84328288059251,57 L 42.499999999999986,57 L-17.84328288059254,57&quot; class=&quot;edge&quot; id=&quot;L_db_server_0&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;architecture-services&quot;&gt;&lt;g id=&quot;service-db&quot; class=&quot;architecture-service&quot; transform=&quot;translate(102.84328288059251,17)&quot;&gt;&lt;g dy=&quot;1em&quot; alignment-baseline=&quot;middle&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;middle&quot; transform=&quot;translate(40, 80)&quot;&gt;&lt;g&gt;&lt;rect class=&quot;background&quot; style=&quot;stroke:none&quot;&gt;&lt;/rect&gt;&lt;text y=&quot;-10.1&quot; style=&quot;&quot;&gt;&lt;tspan class=&quot;text-outer-tspan&quot; x=&quot;0&quot; y=&quot;-0.1em&quot; dy=&quot;1.1em&quot;&gt;&lt;tspan font-style=&quot;normal&quot; class=&quot;text-inner-tspan&quot; font-weight=&quot;normal&quot;&gt;PostgreSQL&lt;/tspan&gt;&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;g&gt;&lt;g&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;80&quot; height=&quot;80&quot; viewBox=&quot;0 0 80 80&quot;&gt;&lt;g&gt;&lt;rect width=&quot;80&quot; height=&quot;80&quot; style=&quot;fill:#087ebf;stroke-width:0px&quot;&gt;&lt;/rect&gt;&lt;path id=&quot;IconifyId19a2fee7a3d846afe0&quot; data-name=&quot;4&quot; d=&quot;m20,57.86c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/path&gt;&lt;path id=&quot;IconifyId19a2fee7a3d846afe1&quot; data-name=&quot;3&quot; d=&quot;m20,45.95c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/path&gt;&lt;path id=&quot;IconifyId19a2fee7a3d846afe2&quot; data-name=&quot;2&quot; d=&quot;m20,34.05c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/path&gt;&lt;ellipse id=&quot;IconifyId19a2fee7a3d846afe3&quot; data-name=&quot;1&quot; cx=&quot;40&quot; cy=&quot;22.14&quot; rx=&quot;20&quot; ry=&quot;7.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/ellipse&gt;&lt;line x1=&quot;20&quot; y1=&quot;57.86&quot; x2=&quot;20&quot; y2=&quot;22.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/line&gt;&lt;line x1=&quot;60&quot; y1=&quot;57.86&quot; x2=&quot;60&quot; y2=&quot;22.14&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/line&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g id=&quot;service-server&quot; class=&quot;architecture-service&quot; transform=&quot;translate(-97.84328288059254,17)&quot;&gt;&lt;g dy=&quot;1em&quot; alignment-baseline=&quot;middle&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;middle&quot; transform=&quot;translate(40, 80)&quot;&gt;&lt;g&gt;&lt;rect class=&quot;background&quot; style=&quot;stroke:none&quot;&gt;&lt;/rect&gt;&lt;text y=&quot;-10.1&quot; style=&quot;&quot;&gt;&lt;tspan class=&quot;text-outer-tspan&quot; x=&quot;0&quot; y=&quot;-0.1em&quot; dy=&quot;1.1em&quot;&gt;&lt;tspan font-style=&quot;normal&quot; class=&quot;text-inner-tspan&quot; font-weight=&quot;normal&quot;&gt;API&lt;/tspan&gt;&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;g&gt;&lt;g&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;80&quot; height=&quot;80&quot; viewBox=&quot;0 0 80 80&quot;&gt;&lt;g&gt;&lt;rect width=&quot;80&quot; height=&quot;80&quot; style=&quot;fill:#087ebf;stroke-width:0px&quot;&gt;&lt;/rect&gt;&lt;rect x=&quot;17.5&quot; y=&quot;17.5&quot; width=&quot;45&quot; height=&quot;45&quot; rx=&quot;2&quot; ry=&quot;2&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/rect&gt;&lt;line x1=&quot;17.5&quot; y1=&quot;32.5&quot; x2=&quot;62.5&quot; y2=&quot;32.5&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/line&gt;&lt;line x1=&quot;17.5&quot; y1=&quot;47.5&quot; x2=&quot;62.5&quot; y2=&quot;47.5&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/line&gt;&lt;g&gt;&lt;path d=&quot;m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:#fff;stroke-width:0px&quot;&gt;&lt;/path&gt;&lt;path d=&quot;m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&gt;&lt;path d=&quot;m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:#fff;stroke-width:0px&quot;&gt;&lt;/path&gt;&lt;path d=&quot;m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&gt;&lt;path d=&quot;m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:#fff;stroke-width:0px&quot;&gt;&lt;/path&gt;&lt;path d=&quot;m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&gt;&lt;circle cx=&quot;32.5&quot; cy=&quot;25&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;27.5&quot; cy=&quot;25&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;22.5&quot; cy=&quot;25&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;/g&gt;&lt;g&gt;&lt;circle cx=&quot;32.5&quot; cy=&quot;40&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;27.5&quot; cy=&quot;40&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;22.5&quot; cy=&quot;40&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;/g&gt;&lt;g&gt;&lt;circle cx=&quot;32.5&quot; cy=&quot;55&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;27.5&quot; cy=&quot;55&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;circle cx=&quot;22.5&quot; cy=&quot;55&quot; r=&quot;.75&quot; style=&quot;fill:#fff;stroke:#fff;stroke-miterlimit:10&quot;&gt;&lt;/circle&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;architecture-groups&quot;&gt;&lt;rect id=&quot;group-api&quot; x=&quot;-140.34328288059254&quot; y=&quot;-25.5&quot; width=&quot;370.6865657611851&quot; height=&quot;182&quot; class=&quot;node-bkg&quot;&gt;&lt;/rect&gt;&lt;g&gt;&lt;g transform=&quot;translate(-139.34328288059254, -24.5)&quot;&gt;&lt;g&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;30&quot; height=&quot;30&quot; viewBox=&quot;0 0 80 80&quot;&gt;&lt;g&gt;&lt;rect width=&quot;80&quot; height=&quot;80&quot; style=&quot;fill:#087ebf;stroke-width:0px&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;m65,47.5c0,2.76-2.24,5-5,5H20c-2.76,0-5-2.24-5-5,0-1.87,1.03-3.51,2.56-4.36-.04-.21-.06-.42-.06-.64,0-2.6,2.48-4.74,5.65-4.97,1.65-4.51,6.34-7.76,11.85-7.76.86,0,1.69.08,2.5.23,2.09-1.57,4.69-2.5,7.5-2.5,6.1,0,11.19,4.38,12.28,10.17,2.14.56,3.72,2.51,3.72,4.83,0,.03,0,.07-.01.1,2.29.46,4.01,2.48,4.01,4.9Z&quot; style=&quot;fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/g&gt;&lt;/g&gt;&lt;g dy=&quot;1em&quot; alignment-baseline=&quot;middle&quot; dominant-baseline=&quot;start&quot; text-anchor=&quot;start&quot; transform=&quot;translate(-106.34328288059254, -18.5)&quot;&gt;&lt;g&gt;&lt;rect class=&quot;background&quot; style=&quot;stroke:none&quot;&gt;&lt;/rect&gt;&lt;text y=&quot;-10.1&quot; style=&quot;&quot;&gt;&lt;tspan class=&quot;text-outer-tspan&quot; x=&quot;0&quot; y=&quot;-0.1em&quot; dy=&quot;1.1em&quot;&gt;&lt;tspan font-style=&quot;normal&quot; class=&quot;text-inner-tspan&quot; font-weight=&quot;normal&quot;&gt;Backend&lt;/tspan&gt;&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;Can’t get much simpler than that!&lt;/p&gt;
&lt;h2 id=&quot;contenders&quot;&gt;Contenders&lt;a class=&quot;anchor&quot; href=&quot;#contenders&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have a bit of experience with the big three (AWS, GCP, and Azure) hosting providers so I wanted give them a shot but I’m certainly am not an expert in any of them to bias my decision one way or the other.  During my initial search for options I also found &lt;a href=&quot;https://dev.to/dkechag/cloud-provider-comparison-2024-vm-performance-price-3h4l?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this article on VM Performance / Price&lt;/a&gt; that proved helpful in finding new options.  Since it was focused on synthetic benchmarks and not hosting an API and database I still wanted to continue with my test to see what kind of actual performance I would get.&lt;/p&gt;
&lt;p&gt;Here’s the full list of hosts I came up with to try&lt;/p&gt;
&lt;div class=&quot;grid grid-cols-3&quot;&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;The Upstarts&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://neon.tech/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Neon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://render.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Render&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://supabase.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Supabase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.heroku.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vercel.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vercel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;The 400lb Gorillas&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cloud.google.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Azure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aws.amazon.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oracle.com/cloud/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Oracle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;The Traditional VPS Hosts&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/products/app-platform?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Digital Ocean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.linode.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Linode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.hetzner.com/cloud/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hetzner&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There were a number of other hosting platforms I looked into that got disqualified for one reason or another.  Many made you pay for the servers all up front, and only had yearly deals which wasn’t going to work for this test.  Others just looked straight up predatory and not a business I’d want to know my credit card number.&lt;/p&gt;
&lt;p&gt;During my research I also found &lt;a href=&quot;https://cloud66.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cloud 66&lt;/a&gt;.  This is not a hosting platform but actually a product that manages deploying your apps and databases to cloud providers or your own VPS.  It also can manage database backups, autoscaling, and monitoring which sounds great as a uniform way to manage servers and avoid vendor lock in.  I’d also be remiss if I didn’t mention &lt;a href=&quot;https://caprover.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Caprover&lt;/a&gt; which I contributed to last year and use to host this site.  It’s similar to Cloud 66 in that it manages docker app deploys, gives you monitoring and a UI, but doesn’t have database backup capability and is much more DIY than Cloud 66.  So for this usecase I chose not to use it.&lt;/p&gt;
&lt;h2 id=&quot;benchmark-setup&quot;&gt;Benchmark Setup&lt;a class=&quot;anchor&quot; href=&quot;#benchmark-setup&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To consistently test each host I set up an &lt;a href=&quot;https://www.artillery.io/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Artillery&lt;/a&gt; load test that hits the site categorization API.  Each request picks 15 random URL’s from a list of 350 to have the API categorize.  The API is mostly read heavy for this operation with a couple queries per request, but also does a few writes to separate tables.&lt;/p&gt;
&lt;p&gt;Before each test I seeded the new database with around 21 thousand rows of categorized URLs to have the queries return meaningful data.&lt;/p&gt;
&lt;p&gt;For the load test itself I setup Artillery to run in phases of 10 seconds each, starting at 5 requests per second (RPS), then going to 10, 50, 100, and 500.&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;anchor&quot; href=&quot;#results&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For each host I documented my setup and deployment experience as well as any bugs or documentation problems that I hit along the way.  These of course shouldn’t be deal breakers but are good to know for your own user experience, especially if you’re using the host for the first time.&lt;/p&gt;
&lt;h3 id=&quot;render&quot;&gt;Render&lt;a class=&quot;anchor&quot; href=&quot;#render&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As my first deploy target there were a few bumps that required code updates to fix a database pool connection issues and accept a connection string environment variable, but once I sorted that out the code I deployed was exactly the same to all the hosts.&lt;/p&gt;
&lt;p&gt;The first instance I created was in Ohio US East with the free tier which gives you such an &lt;em&gt;overwhelmingly generous&lt;/em&gt; 0.1 CPU and 256MB RAM with 1GB Storage.  The basics instance went up pretty quickly but it took quite a few minutes before the deploy started cloning the repo.  Probably shouldn’t expect much from the free tier though.&lt;/p&gt;
&lt;p&gt;It took me a few minutes to figure out how to connect to the Postgres DB from my local machine to run the seeding script (turned out to be the hostname not including the remote url which I had to dig for) but the deploy and mostly worked first time.  A miracle in devops history indeed.  The only problem was a bug in my code for another place not using the env var for the connection string.&lt;/p&gt;
&lt;p&gt;On the free tier though your app shuts down all the time after a minute of inactivity.  After this happened I tried using the restart button but that didn’t do anything, so I had to run a full deploy to get it responding again.&lt;/p&gt;
&lt;style&gt;astro-island,astro-slot,astro-static-slot{display:contents}&lt;/style&gt;&lt;script&gt;(()=&gt;{var e=async t=&gt;{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(&quot;astro:only&quot;));})();&lt;/script&gt;&lt;script&gt;(()=&gt;{var A=Object.defineProperty;var g=(i,o,a)=&gt;o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=&gt;g(i,typeof o!=&quot;symbol&quot;?o+&quot;&quot;:o,a);{let i={0:t=&gt;m(t),1:t=&gt;a(t),2:t=&gt;new RegExp(t),3:t=&gt;new Date(t),4:t=&gt;new Map(a(t)),5:t=&gt;new Set(a(t)),6:t=&gt;BigInt(t),7:t=&gt;new URL(t),8:t=&gt;new Uint8Array(t),9:t=&gt;new Uint16Array(t),10:t=&gt;new Uint32Array(t),11:t=&gt;1/0*t},o=t=&gt;{let[l,e]=t;return l in i?i[l](e):void 0},a=t=&gt;t.map(o),m=t=&gt;typeof t!=&quot;object&quot;||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=&gt;[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,&quot;Component&quot;);d(this,&quot;hydrator&quot;);d(this,&quot;hydrate&quot;,async()=&gt;{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest(&quot;astro-island[ssr]&quot;);if(e){e.addEventListener(&quot;astro:hydrate&quot;,this.hydrate,{once:!0});return}let c=this.querySelectorAll(&quot;astro-slot&quot;),n={},h=this.querySelectorAll(&quot;template[data-astro-template]&quot;);for(let r of h){let s=r.closest(this.tagName);s!=null&amp;&amp;s.isSameNode(this)&amp;&amp;(n[r.getAttribute(&quot;data-astro-template&quot;)||&quot;default&quot;]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&amp;&amp;s.isSameNode(this)&amp;&amp;(n[r.getAttribute(&quot;name&quot;)||&quot;default&quot;]=r.innerHTML)}let p;try{p=this.hasAttribute(&quot;props&quot;)?m(JSON.parse(this.getAttribute(&quot;props&quot;))):{}}catch(r){let s=this.getAttribute(&quot;component-url&quot;)||&quot;&lt;unknown&gt;&quot;,v=this.getAttribute(&quot;component-export&quot;);throw v&amp;&amp;(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute(&quot;props&quot;),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute(&quot;client&quot;)}),this.removeAttribute(&quot;ssr&quot;),this.dispatchEvent(new CustomEvent(&quot;astro:hydrate&quot;))});d(this,&quot;unmount&quot;,()=&gt;{this.isConnected||this.dispatchEvent(new CustomEvent(&quot;astro:unmount&quot;))})}disconnectedCallback(){document.removeEventListener(&quot;astro:after-swap&quot;,this.unmount),document.addEventListener(&quot;astro:after-swap&quot;,this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute(&quot;await-children&quot;)||document.readyState===&quot;interactive&quot;||document.readyState===&quot;complete&quot;)this.childrenConnectedCallback();else{let e=()=&gt;{document.removeEventListener(&quot;DOMContentLoaded&quot;,e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=&gt;{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&amp;&amp;this.lastChild.nodeValue===&quot;astro:end&quot;&amp;&amp;(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener(&quot;DOMContentLoaded&quot;,e)}}async childrenConnectedCallback(){let e=this.getAttribute(&quot;before-hydration-url&quot;);e&amp;&amp;await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute(&quot;opts&quot;)),c=this.getAttribute(&quot;client&quot;);if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=&gt;this.start(),{once:!0});return}try{await Astro[c](async()=&gt;{let n=this.getAttribute(&quot;renderer-url&quot;),[h,{default:p}]=await Promise.all([import(this.getAttribute(&quot;component-url&quot;)),n?import(n):()=&gt;()=&gt;{}]),u=this.getAttribute(&quot;component-export&quot;)||&quot;default&quot;;if(!u.includes(&quot;.&quot;))this.Component=h[u];else{this.Component=h;for(let f of u.split(&quot;.&quot;))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute(&quot;component-url&quot;)}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,&quot;observedAttributes&quot;,[&quot;props&quot;]),customElements.get(&quot;astro-island&quot;)||customElements.define(&quot;astro-island&quot;,y)}})();&lt;/script&gt;&lt;astro-island uid=&quot;rhNbz&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;45rps&amp;quot;],[0,&amp;quot;85rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,1720.2],[0,2369],[0,4965.3],[0,8868.4],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,2780],[0,4147.4],[0,5826.9],[0,9230.4],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,3072.4],[0,5826.9],[0,6439.7],[0,9416.8],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,3134.5],[0,8352],[0,8024.5],[0,9801.2],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,341],[0,786]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Render Free&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;Pretty poor results if I do say so myself. But let’s upgrade to the paid tier to give them a fair shake.&lt;/p&gt;
&lt;p&gt;Even getting a 0.5 CPU 1gb RAM instance is $19/mo which is above the budget threshold so I went with their most basic paid plan to retest. The DB is $6/mo for 256MB RAM and 0.1 CPU (lol is this 2005?) and the “App Starter” is $7/mo for 512MB RAM and 0.5 CPU.&lt;/p&gt;
&lt;astro-island uid=&quot;Z2eP3zQ&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;15rps&amp;quot;],[0,&amp;quot;40rps&amp;quot;],[0,&amp;quot;65rps&amp;quot;],[0,&amp;quot;154rps&amp;quot;],[0,&amp;quot;224rps&amp;quot;],[0,&amp;quot;234rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,273.2],[0,228.2],[0,2101.1],[0,7260.8],[0,null],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,415.8],[0,368.8],[0,3464.1],[0,8868.4],[0,null],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,424.2],[0,468.8],[0,4403.8],[0,9607.1],[0,null],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,424.2],[0,658.6],[0,5826.9],[0,9607.1],[0,null],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,135],[0,622],[0,1483],[0,1956]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Render Paid&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;Better, but really not that good.&lt;/p&gt;
&lt;h3 id=&quot;digital-ocean&quot;&gt;Digital Ocean&lt;a class=&quot;anchor&quot; href=&quot;#digital-ocean&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For DO I exceeded the budget by a bit to be able to use their &lt;a href=&quot;https://www.digitalocean.com/products/managed-databases-postgresql?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;fully managed PostgreSQL&lt;/a&gt; offering that starts at $15 a month and then their &lt;a href=&quot;https://www.digitalocean.com/products/app-platform?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;app platform&lt;/a&gt; which starts at $5 per month for 1 shared vCPU, 512MB RAM, and 50GB bandwidth hosted in their New York data center.&lt;/p&gt;
&lt;p&gt;First impressions were good with an easy setup for both the DB and app but it took a little while to sort out a few configuration issues with the health check using the wrong port, the database &lt;a href=&quot;https://docs.digitalocean.com/products/databases/postgresql/how-to/manage-connection-pools?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;connection pool&lt;/a&gt; settings, and environment variables for the DB connection.  After the first couple times editing the app config to change an environment variable it’s a bit annoying the whole app has to rebuild and redeploy which takes a couple minutes when it could just be a container restart taking seconds.&lt;/p&gt;
&lt;p&gt;As I was running the test it’s nice to see they have built in load charts, query stats, and DB logs.  During peak load the app still didn’t even come close to maxing out CPU usage or memory in app or DB which makes me think connections are the bottleneck.  That will have to be a separate investigation though since I’m trying to keep everything as similar as possible between tests.&lt;/p&gt;
&lt;astro-island uid=&quot;ZUMWv1&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;],[0,&amp;quot;225rps&amp;quot;],[0,&amp;quot;233rps&amp;quot;],[0,&amp;quot;280rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,74.4],[0,71.5],[0,71.5],[0,162.4],[0,2369],[0,9230.4],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,85.6],[0,82.3],[0,80.6],[0,232.8],[0,3752.7],[0,9416.8],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,87.4],[0,96.6],[0,94.6],[0,333.7],[0,4403.8],[0,9607.1],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,138.4],[0,125.2],[0,135.7],[0,487.9],[0,7557.1],[0,9801.2],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,0],[0,0],[0,1726],[0,1857]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Digital Ocean&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;h3 id=&quot;linode&quot;&gt;Linode&lt;a class=&quot;anchor&quot; href=&quot;#linode&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I was going to run the test it on my existing tiny server that runs this site but then thought that wouldn’t be a fair comparison so I created a new server for the test.&lt;/p&gt;
&lt;p&gt;To stay on budget the instance had to be 1 shared CPU, 2gb RAM for $12/mo US East, Newark NJ&lt;/p&gt;
&lt;astro-island uid=&quot;MMuM&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;],[0,&amp;quot;500rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,77.5],[0,68.7],[0,9416.8],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,85.6],[0,74.4],[0,9607.1],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,127.8],[0,85.6],[0,9801.2],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,202.4],[0,179.5],[0,9999.2],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,425],[0,1018],[0,4428]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Linode&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;h3 id=&quot;aws&quot;&gt;AWS&lt;a class=&quot;anchor&quot; href=&quot;#aws&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;AWS is a behemoth of complexity but since I was just using one VPS with Cloud 66 handling the hard parts of deploys it only took less than an hour to figure out IAM permissions and credentials for Cloud 66 to use and which instance type is at the right price point.&lt;/p&gt;
&lt;p&gt;I landed on trying a &lt;code&gt;t3.small&lt;/code&gt; on us-east-1 (N. Virginia) which has 2 vCPUs, 2GB RAM and should be ~$15/mo.&lt;/p&gt;
&lt;astro-island uid=&quot;1MIwuA&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;40rps&amp;quot;],[0,&amp;quot;80rps&amp;quot;],[0,&amp;quot;310rps&amp;quot;],[0,&amp;quot;500rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,67.4],[0,61],[0,92.8],[0,262.5],[0,4492.8],[0,8692.8]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,87.4],[0,70.1],[0,104.6],[0,1274.3],[0,6064.7],[0,9230.4]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,89.1],[0,90.9],[0,138.4],[0,1863.5],[0,6702.6],[0,9607.1]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,117.9],[0,102.5],[0,242.3],[0,2231],[0,7117],[0,9801.2]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,0],[0,1584],[0,2681]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;AWS&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;I wanted to compare the single VPS solution to “the amazon way” using RDS (and try out Aurora) and Fargate with Elastic Container Service (ECS) for the app but playing with the AWS pricing calculator quickly proved that to be a non-starter.&lt;/p&gt;
&lt;p&gt;The smallest RDS instance for just PostgreSQL is the &lt;code&gt;db.m1.small&lt;/code&gt; machine instance and that’ll run you $43.80/mo by itself for a single AZ. Then tack on $2.30/mo for the minimum 20gb storage and $1.90/mo to backup the 20gb.  With PostgreSQL compatible Aurora the smallest instance is &lt;code&gt;db.r4.large&lt;/code&gt; which is $211.70/mo plus DB storage prices that vary wildly on baseline IO rates which I have no idea what to expect.  The good news is that it’s only $0.42/mo for the same 20gb backup!&lt;/p&gt;
&lt;p&gt;With Aurora &lt;em&gt;Serverless&lt;/em&gt; the minimum you can do is 0.5 “Aurora Capacity Units (ACUs)” per hour which are described as “Each ACU is a combination of approximately 2 gibibytes (GiB) of memory, corresponding CPU, and networking”.  For what sounds like a tiny amount of power will still run you $43.80/mo with the same DB storage and backup prices as above.&lt;/p&gt;
&lt;p&gt;If you actually want to run an app as well that’ll be extra!  Calculating the cost for Fargate with 50% utilization, 2vCPU 8GB RAM for just one container came out to $42.53/mo.&lt;/p&gt;
&lt;p&gt;I guess the “the Amazon way” is not as cheap as I thought after all…&lt;/p&gt;
&lt;h3 id=&quot;gcp&quot;&gt;GCP&lt;a class=&quot;anchor&quot; href=&quot;#gcp&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A first glance at a dedicated Postgres DB in the &lt;a href=&quot;https://cloud.google.com/products/calculator?hl=en&amp;dl=CjhDaVEwTkROaE5UazVOeTAxWm1JMkxUUXhOell0WW1KaU9TMHpNalJsTUdVeU5qWmtORGdRQVE9PRAHGiQ5ODkzRDc1OC0zQTM3LTQxOTUtQTkyMi1GM0VDNEIxNjIxQjY&amp;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;calculator&lt;/a&gt; shows it’s well outside my price range so I’ll once again sift through the plethora of &lt;a href=&quot;https://cloud.google.com/compute/vm-instance-pricing?hl=en#section-1&amp;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VM options&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The best equivalent instance I found is an &lt;code&gt;e2-small&lt;/code&gt; with 2 vCPU and 2 GiB RAM for $14/mo.  Choosing &lt;code&gt;us-east4&lt;/code&gt; in N. Virginia to be a comparable location for the latency.&lt;/p&gt;
&lt;p&gt;The signup experience had a new wrinkle to it that no other provider made me do.  You have to verify your credit card by waiting for pending charges to show up on the statement and then enter the amounts. After 15 minutes of refreshing my statement I gave up and went and did something else useful.  Only after coming back 45 minutes later the charge showed up and I could proceed with waiting another 25 minutes for the app to deploy (the longest of any provider by far).&lt;/p&gt;
&lt;p&gt;From &lt;a href=&quot;https://console.cloud.google.com/apis/library/compute.googleapis.com?&amp;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Compute Engine API&lt;/a&gt; page clicking manage just sends me back to same page&lt;/p&gt;
&lt;astro-island uid=&quot;K7530&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;103rps&amp;quot;],[0,&amp;quot;497rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,727.9],[0,2231],[0,6187.2],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,742.6],[0,2515.5],[0,7260.8],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,757.6],[0,3011.6],[0,8692.8],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,963.1],[0,3464.1],[0,9230.4],[0,null],[0,null]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,487],[0,1033]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;GCP&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;Welp, that was disappointing&lt;/p&gt;
&lt;h3 id=&quot;azure&quot;&gt;Azure&lt;a class=&quot;anchor&quot; href=&quot;#azure&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once again from poking around the &lt;a href=&quot;https://azure.microsoft.com/en-us/pricing/calculator/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Pricing Calculator&lt;/a&gt;, dedicated DB instances are way too expensive and cryptically named &lt;code&gt;Dadsv5 - Series&lt;/code&gt; which means absolutely nothing unless you have the decoder ring.  No surprise the &lt;a href=&quot;https://azure.microsoft.com/en-us/pricing/details/virtual-machines/linux/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;list of virtual machines is nuts&lt;/a&gt; but narrowing down by price once again I land on the &lt;code&gt;B1ms&lt;/code&gt; instance with 1 core, 2GB RAM for $15/mo deployed to US East in Virginia.&lt;/p&gt;
&lt;p&gt;I have used Azure a bit before so I know a bit of what to expect but just trying to follow the instructions to set up credentials for Cloud 66 to use was like trying to escape a corn maze.  Why are there two different admin dashboards? &lt;a href=&quot;https://entra.microsoft.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://entra.microsoft.com&lt;/a&gt; vs &lt;a href=&quot;https://portal.azure.com?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://portal.azure.com&lt;/a&gt;    Why don’t the tabs look like tabs?  When I tried to add a role to a subscription for an app &lt;a href=&quot;https://learn.microsoft.com/en-us/entra/identity-platform/howto-create-service-principal-portal?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;following the instructions&lt;/a&gt; I couldn’t find the “Contributor” role because it was hidden behind another tab “Privileged administrator roles” instead of “Job function roles” that just looked like a sub-heading.&lt;/p&gt;
&lt;p&gt;The Cloud 66 docs are light on this process and the first couple deploys failed with these errors on which “namespaces” the subscriptions need.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;An exception occurred in your cloud during server creation: Can&amp;#39;t create a default Virtual Network in Azure cloud: The Azure API responded with HTTP error 409 and error code(s) MissingSubscriptionRegistration: The subscription is not registered to use namespace &amp;#39;Microsoft.Network&amp;#39;. See https://aka.ms/rps-not-found for how to register subscriptions.. If the problem persists please contact support.. If the problem persists please contact support. master&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s also annoying that Cloud 66 has to create a new app (even with copied vars) to retry initial deployment after it fails. It claims it will clone all the variables of the app deployment but actually it forgets the deployment target, machine type, and DB each time.  Finally got it working though for the first successful deploy taking 13 minutes.&lt;/p&gt;
&lt;astro-island uid=&quot;Z20Tsyy&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;],[0,&amp;quot;492rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,62.2],[0,61],[0,85.6],[0,1755],[0,6187.2]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,77.5],[0,64.7],[0,96.6],[0,2671],[0,7407.5]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,80.6],[0,113.3],[0,3197.8],[0,8186.6]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,87.4],[0,92.8],[0,295.9],[0,3678.4],[0,8352]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,0],[0,3900]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Azure&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;h3 id=&quot;hetzner&quot;&gt;Hetzner&lt;a class=&quot;anchor&quot; href=&quot;#hetzner&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After all that messing around with the big cloud providers the signup and setup process for Hetzner was a breath of fresh air.  All Cloud 66 needed was creating an API key that took a few clicks.&lt;/p&gt;
&lt;p&gt;There was a couple different options at my price point in their Ashburn Virginia data center so I wanted to try out both the dedicated and shared CPU instances.&lt;/p&gt;
&lt;p&gt;First deploy was with the dedicated 2 vCPU, 8GB RAM, 80GB storage for $15/mo which first deployed in 8 minutes.&lt;/p&gt;
&lt;astro-island uid=&quot;uX3qS&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;27rps&amp;quot;],[0,&amp;quot;59rps&amp;quot;],[0,&amp;quot;148rps&amp;quot;],[0,&amp;quot;509rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,61],[0,58.6],[0,61],[0,64.7],[0,74.4],[0,5487.5]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,61],[0,64.7],[0,71.5],[0,87.4],[0,6976.1]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,63.4],[0,71.5],[0,80.6],[0,144],[0,7709.8]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,82.3],[0,83.9],[0,96.6],[0,854.2],[0,8186.6]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,0],[0,0],[0,2644]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Hetzner Dedicated&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;Then I tried their shared 3 vCPU, 4GB RAM, 80GB storage instance for $11/mo.&lt;/p&gt;
&lt;astro-island uid=&quot;1BFrgz&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;],[0,&amp;quot;264rps&amp;quot;],[0,&amp;quot;631rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p50&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,58.6],[0,59.7],[0,63.4],[0,73],[0,658.6],[0,4492.8]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 85%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p75&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,62.2],[0,67.4],[0,70.1],[0,80.6],[0,1085.9],[0,4583.6]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 63%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p90&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,77.5],[0,85.6],[0,74.4],[0,94.6],[0,1326.4],[0,4676.2]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 38%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;p99&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,133],[0,144],[0,87.4],[0,169],[0,1620],[0,4676.2]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(200, 70%, 18%)&amp;quot;]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Error Count&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0],[0,0],[0,0],[0,0],[0,0],[0,120]]],&amp;quot;backgroundColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;borderColor&amp;quot;:[0,&amp;quot;hsl(0 77% 53%)&amp;quot;],&amp;quot;pointRadius&amp;quot;:[0,8],&amp;quot;pointHoverRadius&amp;quot;:[0,9]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Hetzner Shared&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;h2 id=&quot;dnf&quot;&gt;DNF&lt;a class=&quot;anchor&quot; href=&quot;#dnf&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All of the following providers I tried but wasn’t able to get them working for one reason or another.  Some of them I’m sure I could get working if I spent more time on it but I disqualified them for myself for being a time suck.&lt;/p&gt;
&lt;h3 id=&quot;supabase&quot;&gt;Supabase&lt;a class=&quot;anchor&quot; href=&quot;#supabase&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First impression creating a new app: “Network error trying to create new resource”.  Second impression: “Project with name X already exists in your organization”.&lt;/p&gt;
&lt;p&gt;After actually creating the DB it took a bit of searching around how to find the connection string to use to directly connect to the db for seeding.&lt;/p&gt;
&lt;p&gt;AAannnd then I realized you can’t actually deploy a full containerized app, only edge functions which defeats the point of hosting your api close to your db for me.&lt;/p&gt;
&lt;h3 id=&quot;heroku&quot;&gt;Heroku&lt;a class=&quot;anchor&quot; href=&quot;#heroku&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I did use Heroku like 10 years ago and surprisingly my password manager has the login saved. But of course trying to use it prompted the error “There was a problem with your login”.  Went through the forgot password flow but never got an email, so time to sign up again I guess.  There’s an annoying signup questionnaire and mandatory 2FA right out of the gate which slows down the whole process.&lt;/p&gt;
&lt;p&gt;Looking through all “essential” DB plans they all seem to be same except for storage limit, and are listed for $5/mo with “0 Bytes RAM, 1GB storage”.  Pretty sure there’s a mistake in there but I give it a shot anyways and run straight into a 404 page with a error popup.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/heroku_404.3cQgU8Mq_Z24i5Aj.webp&quot; alt=&quot;Heroku fail&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1481&quot; height=&quot;618&quot;&gt;&lt;/p&gt;
&lt;p&gt;I guess they don’t offer that one anymore and I’ll have to use the $50/month plan with 4GB RAM, 64GB storage, and 120 connections instead?  Nope that one doesn’t work either…  I had to look up a youtube tutorial to find out you have to create an app first and then attach postgres as an add on… Ok I guess I’ll do that even though it seems backwards to me.  I create the add on and then go click the “Heroku Postgres” link to find out the credentials for seeding and it does ** exactly what I expect ** … and opens the favicon in a new tab &lt;a href=&quot;https://addons-sso.heroku.com/favicon.ico?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://addons-sso.heroku.com/favicon.ico&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/heroku_db.Duih2sRy_2enpNW.webp&quot; alt=&quot;Heroku fail&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1287&quot; height=&quot;212&quot;&gt;&lt;/p&gt;
&lt;p&gt;Going back to the page and trying agin it works, I guess their JS was just slow or broken? On the next page I’m amused to see they actually just use Amazon RDS under the hood.&lt;/p&gt;
&lt;p&gt;The next step is to try to figure out how to deploy the app. Heroku apparently can’t figure out there’s a docker file, from docs I found looks like you have to set up a heroku yml file. Tried a version of that which didn’t work, then see you should use this &lt;a href=&quot;https://devcenter.heroku.com/articles/buildpacks?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;build pack&lt;/a&gt; thing.&lt;/p&gt;
&lt;p&gt;The article doesn’t really say how to use them in your project and there’s &lt;a href=&quot;https://github.com/heroku/buildpacks-dotnet?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;https://github.com/heroku/heroku-buildpack-dotnet?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;different&lt;/a&gt; flavors of build packs but the descriptions are gobbltygook if you don’t already know what they are.&lt;/p&gt;
&lt;p&gt;That all seems like quite the hassle for this test so I switch to just use the container registry method.  But come to find out there’s no way to do that in the UI, you have to install the heroku CLI, sigh…&lt;/p&gt;
&lt;p&gt;I go through their instructions for pushing a container but of course it fails at&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;heroku container:push cat-search-api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ›   Error: The following error occurred:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ›     Missing required flag app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ›   See more help with --help&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Added the &lt;code&gt;--app&lt;/code&gt; parameter that’s missing in all their examples and then got another error:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;heroku container:push --app=cat-search web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ›   Error: This command is for Docker apps only. Switch stacks by running heroku stack:set container. Or, to deploy ⬢ cat-search with heroku-24, run git push heroku main instead.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did that and now it rebuilds the docker image even though nothings changed, and I think it deploys, but there wasn’t anywhere to specify the environment variables during this process.  So you have to switch back to the UI and add them in “Config Vars”.&lt;/p&gt;
&lt;p&gt;Finally open up the deployed app url and of course get an app error.  Turns out the app inside the container can’t bind to port 8080.  Mess around with thing some more and try both port 80 and 443. No luck…&lt;/p&gt;
&lt;p&gt;And this is where my Heroku story ends:  2 hours after it started with nothing to show for it except the experience to know I’ll never use Heroku again.&lt;/p&gt;
&lt;h3 id=&quot;neon&quot;&gt;Neon&lt;a class=&quot;anchor&quot; href=&quot;#neon&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Should have found this in the initial search but found out it doesn’t support deploying an app alongside the DB.&lt;/p&gt;
&lt;h3 id=&quot;vercel&quot;&gt;Vercel&lt;a class=&quot;anchor&quot; href=&quot;#vercel&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also should have found earlier that &lt;a href=&quot;https://vercel.com/guides/does-vercel-support-docker-deployments?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vercel doesn’t support docker deploys&lt;/a&gt;.  This one did surprise me a bit since I know they let you deploy edge functions to run Next.js apps and I thought they were angling to be a more comprehensive hosting platform.&lt;/p&gt;
&lt;h3 id=&quot;oracle&quot;&gt;Oracle&lt;a class=&quot;anchor&quot; href=&quot;#oracle&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To be honest, before reading the &lt;a href=&quot;https://dev.to/dkechag/cloud-provider-comparison-2024-vm-performance-price-3h4l?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cloud provider performance article&lt;/a&gt; I didn’t even know what Oracle really did anymore other than sell database lock in.  But apparently they have good performance to price ratio so lets give them a shot and see.&lt;/p&gt;
&lt;p&gt;After signing up I go to create a VM instance that’s in the price ballpark and go for the &lt;code&gt;Compute - Standard - E5 - Flex AMD&lt;/code&gt; instance with 2 OCPU and 8GB RAM running Ubuntu 24 but I’m not really sure on the price when selecting it since it doesn’t list it.  After it’s up I go to the &lt;a href=&quot;https://cloud.oracle.com/billing/usage-statements?region=us-ashburn-1&amp;ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billing Screen&lt;/a&gt; to see if it lists an estimated cost, but that page has an error.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/oracle_error.CSa2ao2S_Z3KTx8.webp&quot; alt=&quot;Oracle error&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1427&quot; height=&quot;614&quot;&gt;&lt;/p&gt;
&lt;p&gt;I had to go to the public &lt;a href=&quot;https://www.oracle.com/cloud/costestimator.html?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cost Estimator&lt;/a&gt; to see it’s actually $56/mo.  Outside my budget but lets try it anyways, so I get it registered in Cloud 66 as a custom server.&lt;/p&gt;
&lt;p&gt;The first deployment fails after 19 minutes with the error “system services failed to start”.  Searching around a bit for things to try I find to run this command to get Kubernetes logs.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;journalctl -u kubelet&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes catppuccin-latte dracula-soft&quot; style=&quot;background-color:#eff1f5;--shiki-dark-bg:#282A36;color:#4c4f69;--shiki-dark:#f6f6f4;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Mar 14 02:03:33 master kubelet[23739]: I0314 02:03:33.537146   23739 scope.go:117] &amp;quot;RemoveContainer&amp;quot; containerID=&amp;quot;93a9c646c1dab98ef4c0707f35b4d95d96dd10612081a6fe22fc43523b9c1df3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Mar 14 02:03:33 master kubelet[23739]: E0314 02:03:33.537283   23739 pod_workers.go:1301] &amp;quot;Error syncing pod, skipping&amp;quot; err=&amp;quot;failed to \&amp;quot;StartContainer\&amp;quot; for \&amp;quot;k8s-event-relay\&amp;quot; with CrashLoopBackOff: \&amp;quot;back-off 5m0s restarting failed container=k8s-event-relay pod=k8s-event-relay-6885c57f84-ph7rc_kube-system(ef57&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not sure where to go from here I try a different instance with 1 OCPU, 8GB RAM.  Same problem.  One more time, this time with Ubuntu 22, on the 1 OCPU, 8GB RAM.  Failed again and since these were all fresh machines with the Ubuntu versions Cloud 66 supports I don’t particularly feel like spending more time messing with it and give up. I’m hesitant to blame Cloud 66 though since the custom server setup worked flawlessly for Linode.&lt;/p&gt;
&lt;h2 id=&quot;combined-results&quot;&gt;Combined Results&lt;a class=&quot;anchor&quot; href=&quot;#combined-results&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For all the hosts I was able to deploy to here’s the combined view with their p90 times across the different load rates.  In the cases where the load numbers didn’t fall exactly along the delineations I linearly interpolated to get a more accurate result.&lt;/p&gt;
&lt;astro-island uid=&quot;1t2kzX&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Line.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;5rps&amp;quot;],[0,&amp;quot;10rps&amp;quot;],[0,&amp;quot;50rps&amp;quot;],[0,&amp;quot;100rps&amp;quot;],[0,&amp;quot;500rps&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Render&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,354.7],[0,424.2],[0,9607.1],[0,null],[0,null]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Digital Ocean&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,87.4],[0,96.6],[0,94.6],[0,333.7],[0,null]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Linode&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,202.4],[0,179.5],[0,9999.2],[0,null],[0,null]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;AWS&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,89.1],[0,90.9],[0,569],[0,2283],[0,9607.1]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;GCP&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,963.1],[0,3464.1],[0,9230.4],[0,null],[0,null]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Azure&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,80.6],[0,113.3],[0,3197.8],[0,8186.6]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Hetzner Dedicated&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,83.9],[0,63.4],[0,78],[0,109.8],[0,7709.8]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;Hetzner Shared&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,77.5],[0,85.6],[0,74.4],[0,94.6],[0,3480]]]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;Combined p90&amp;quot;]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;interaction&amp;quot;:[0,{&amp;quot;intersect&amp;quot;:[0,false]}],&amp;quot;scales&amp;quot;:[0,{&amp;quot;x&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false]}],&amp;quot;y&amp;quot;:[0,{&amp;quot;stacked&amp;quot;:[0,false],&amp;quot;type&amp;quot;:[0,&amp;quot;logarithmic&amp;quot;],&amp;quot;title&amp;quot;:[0,{&amp;quot;text&amp;quot;:[0,&amp;quot;Latency (ms)&amp;quot;],&amp;quot;display&amp;quot;:[0,true]}]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Line&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;p&gt;I also wanted to see performance compared to the monthly cost in some way so the best metric I could come up with is taking the ratio &lt;code&gt;RPS / Latency / Monthly Cost&lt;/code&gt; from the p90 values that are shown above.  This ratio will give greater values to the hosts that can deliver more requests at lower latencies for a lower cost.&lt;/p&gt;
&lt;p&gt;So using AWS as an example: &lt;code&gt;50 RPS / 569ms latency / $15 a month = 0.0058&lt;/code&gt; which you can see rounded to 0.006 on its blue bar below.&lt;/p&gt;
&lt;astro-island uid=&quot;bPdwF&quot; component-url=&quot;/home/runner/work/dillonshook.com/dillonshook.com/src/components/charts/Bar.svelte&quot; component-export=&quot;default&quot; renderer-url=&quot;@astrojs/svelte/client.js&quot; props=&quot;{&amp;quot;data&amp;quot;:[0,{&amp;quot;labels&amp;quot;:[1,[[0,&amp;quot;Herzner Shared&amp;quot;],[0,&amp;quot;Herzner Dedicated&amp;quot;],[0,&amp;quot;Azure&amp;quot;],[0,&amp;quot;Digital Ocean&amp;quot;],[0,&amp;quot;AWS&amp;quot;],[0,&amp;quot;Linode&amp;quot;],[0,&amp;quot;Render&amp;quot;],[0,&amp;quot;GCP&amp;quot;]]],&amp;quot;datasets&amp;quot;:[1,[[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;50 RPS / Latency / Dollar&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0.06109481915933528],[0,0.042735042735042736],[0,0.029420417769932334],[0,0.026427061310782242],[0,0.005858230814294083],[0,0.00041670000266688],[0,0.0002739202201880298],[0,0.00038692023871431054]]]}],[0,{&amp;quot;label&amp;quot;:[0,&amp;quot;10 RPS / Latency / Dollar&amp;quot;],&amp;quot;data&amp;quot;:[1,[[0,0.010620220900594734],[0,0.010515247108307044],[0,0.008271298593879239],[0,0.005175983436853002],[0,0.007334066740007333],[0,0.004645113340765515],[0,0.0012407255763170302],[0,0.00020620257340811613]]]}]]]}],&amp;quot;options&amp;quot;:[0,{&amp;quot;indexAxis&amp;quot;:[0,&amp;quot;y&amp;quot;],&amp;quot;elements&amp;quot;:[0,{&amp;quot;bar&amp;quot;:[0,{&amp;quot;borderWidth&amp;quot;:[0,2]}]}],&amp;quot;responsive&amp;quot;:[0,true],&amp;quot;plugins&amp;quot;:[0,{&amp;quot;title&amp;quot;:[0,{&amp;quot;display&amp;quot;:[0,true],&amp;quot;text&amp;quot;:[0,&amp;quot;p90 Performance Per Dollar&amp;quot;]}]}]}]}&quot; ssr client=&quot;only&quot; before-hydration-url=&quot;astro:scripts/before-hydration.js&quot; opts=&quot;{&amp;quot;name&amp;quot;:&amp;quot;Bar&amp;quot;,&amp;quot;value&amp;quot;:&amp;quot;svelte&amp;quot;}&quot;&gt;&lt;/astro-island&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Suffice to say I’ll be using Hetzner for both the ease of setup and best all around performance per dollar.  Surprising to me is Azure coming in second for hosts on the performance per dollar chart however the very complex management console and altered vocabulary for everything is not for those looking to avoid complexity. Also surprising to me is how poorly all the new generation of hosting platforms faired.  All but one was a nonstarter and the only one I did deploy on had awful performance for the price.&lt;/p&gt;
&lt;p&gt;Hopefully this info will help you in your search for hosting!&lt;/p&gt;</content:encoded></item><item><title>Sowing the Seed Data</title><link>https://dillonshook.com/sowing-the-seed-data/</link><guid isPermaLink="true">https://dillonshook.com/sowing-the-seed-data/</guid><pubDate>Thu, 06 Mar 2025 19:51:22 GMT</pubDate><content:encoded>&lt;p&gt;Coming at you here with another Cat Search update! Since last time the new design has been implemented (see below), authentication is mostly done (still need to send emails), and many bugs have been squashed &lt;span class=&quot;inline-block cursor-crosshair hover:rotate-180 transition-all duration-300&quot;&gt;🪳&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;However, I got a little side tracked the last couple days by a “simple” item on my todo list I didn’t even mention last time: &lt;code&gt;Update Seed Data&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-seeding-data&quot;&gt;What is Seeding Data&lt;a class=&quot;anchor&quot; href=&quot;#what-is-seeding-data&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m not entirely sure where the term came from since your data doesn’t typically sprout the same way the seeds in your garden do but for those unfamiliar with the term seeding data it’s just pre-filling your database.  Often times it’s generated fake data just used to test with.&lt;/p&gt;
&lt;p&gt;In my case though it’s not just test data!  The seed data will be used as the initial categorized sites when Cat Search launches.&lt;/p&gt;
&lt;h2 id=&quot;and-why-should-you-bother&quot;&gt;And Why Should You Bother?&lt;a class=&quot;anchor&quot; href=&quot;#and-why-should-you-bother&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the worst first user impressions I can imagine (which is not difficult having experienced this many times myself) is to land on a page full of empty states and placeholders.  It’s a ghost town of the forgotten web where they built it and no one came, clearly destined to decay.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Chinese Ghost City&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1275&quot; height=&quot;683&quot; src=&quot;/_astro/ghost_city.Ku6Nkf45_Z2eQXoq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On the flip side&lt;/strong&gt;, if the app is bustling with activity showing the product value it’s now a happening place you don’t want to miss out on.&lt;/p&gt;
&lt;p&gt;Any user first impression is a critical moment in forming an opinion of what your product does, how is it’s valuable, and &lt;strong&gt;why should anyone care.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you’re not able to get real data in your app when it launches the next best thing is to have a sandbox demo environment for customers to try first, which of course requires a seeding script.  Depending on your app, this make take the form of an ephemeral demo environment or just one that gets reset every so often.&lt;/p&gt;
&lt;p&gt;While the above is the primary reason to seed in my mind, there’s another benefit.&lt;/p&gt;
&lt;p&gt;Let’s face it, production data is generally messier than a kids bedroom after a sugar rush.  There’s all kinds of unexpected edge cases the developers never thought of like really long names, tables that have way more data than expected, and the general bucket of “non-conforming” data from partially deleted records or the result of bugs that were never fixed.  Regardless though, it’s a good habit to update your seed script to include this weird but possible data so that the devs see it every day working and consider how to handle all the edge cases.  This also includes having a realistic amount of data compared to production so the devs get annoyed with any scaling performance problems and just go and fix them.  The bugs won’t be out of sight out of mind if you’re testing with realistic data.&lt;/p&gt;
&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;a class=&quot;anchor&quot; href=&quot;#sources&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With Cat Search my challenge was finding good sources to pull website categories from.  There are a number of companies out there if you search “website category api” that provide APIs for categorizing domains but they’re all exorbitantly expensive and it’s probably against their terms of service to use the data to put them out of business ;-)&lt;/p&gt;
&lt;p&gt;So publicly available lists it had to be.&lt;/p&gt;
&lt;p&gt;I started with the &lt;a href=&quot;https://ahrefs.com/websites?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ahrefs top sites list&lt;/a&gt; which includes categories but had to do a bit of cleaning on it to make it usable and the categories make sense. Like whatsapp.com is not “Internet and Telecom” really.&lt;/p&gt;
&lt;p&gt;Another great source I’m exploring more is good ol’ Wikipedia.  There are list pages like &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Internet_forums?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;List of Internet forums&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_video_game_websites?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;List of Video Game Websites&lt;/a&gt; that list out a bunch of the popular sites.  It does take a bit of scripting to get the actual domains of all the sites though since the links on these pages are to other Wiki pages.&lt;/p&gt;
&lt;p&gt;There’s a few open source projects that helped too.  &lt;a href=&quot;https://github.com/kagisearch/smallweb?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kagi Small Web&lt;/a&gt; is the basis for my Indie Blogs category and &lt;a href=&quot;https://devdocs.io/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;DevDocs&lt;/a&gt; is used for the Official Documentation category.&lt;/p&gt;
&lt;p&gt;The last major source has been &lt;a href=&quot;https://iorate.github.io/ublacklist/subscriptions?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;uBlacklist subscription lists&lt;/a&gt;.  Many of these are sus and go overboard but with a little bit of grooming they provided good lists of spam and AI sites.&lt;/p&gt;
&lt;p&gt;If you know of any other good sources please let me know in the comments!&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;anchor&quot; href=&quot;#results&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With all that seeding work the results speak for themselves.  Across 2 pages of google results many popular queries (😉) only have a couple Uncategorized results.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cat Search Seeded Data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1218&quot; height=&quot;1121&quot; src=&quot;/_astro/design.B1F_SV1i_1OSdjS.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I’m sure there are a number of search queries that I never make which will be much more uncategorized but I’ll have to launch the thing to figure out what those are!&lt;/p&gt;</content:encoded></item><item><title>So What Exactly is MVP Anyways?</title><link>https://dillonshook.com/so-what-exactly-is-mvp-anyways/</link><guid isPermaLink="true">https://dillonshook.com/so-what-exactly-is-mvp-anyways/</guid><description>It&apos;s been a little while since the last project update! Life happens and I also need to get better at switching to a &apos;Build Share Build Share&apos; mode instead of just &apos;Build Build Build Build&apos; mode which is my default.  So here&apos;s what&apos;s happened since last time as well as a thought exercise on what exactly you need for a Minimum Viable Product.</description><pubDate>Thu, 20 Feb 2025 20:56:17 GMT</pubDate><content:encoded>&lt;p&gt;It’s been a little while since the last project update! Life happens and I also need to get better at switching to a “Build Share Build Share” mode instead of just “Build Build Build Build” mode which is my default.  So here’s what’s happened since last time as well as a thought exercise on what exactly you need for a Minimum Viable Product.&lt;/p&gt;
&lt;h2 id=&quot;progress&quot;&gt;Progress&lt;a class=&quot;anchor&quot; href=&quot;#progress&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From last time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My goal for the next update is to get the frontend interacting with the backend to read and set both site votes and categories. Should be easy enough but there’s a lot of stuff I glossed over on both the frontend and backend that I’m sure I’ll be refining as I go.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Goal: Smashed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But that might be because it’s been two and half months since the last update 😅.  But a lot has been accomplished in the limited amount of time I’ve been able to dedicate.&lt;/p&gt;
&lt;p&gt;First off, &lt;strong&gt;I’ve settled on a name for the project: Cat Search!&lt;/strong&gt; It’s short for “Category Search” which is what this is all about.  It lets you categorize all your search engine results into whatever you want to take control of the results you see and how you mentally rank them yourself.  I’ve been toying around with that name in my head for awhile now and since nothing better came to me it stuck.  It’s a great name too since it’s &lt;a href=&quot;/how-hard-is-your-email-to-say&quot;&gt;easy to say&lt;/a&gt;, easy to remember, and easy to make a cute mascot for :)  Even though I’m really a dog person, as you can probably tell from my profile picture, cats are great too.&lt;/p&gt;
&lt;p&gt;Without further ado here’s what the current state of Cat Search looks like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cat Search Current State&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1606&quot; height=&quot;976&quot; src=&quot;/_astro/progress.wbSDtLSo_Z1xllx8.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I got support for both Google and Duck Duck Go working so whenever you search for something the extension parses all the link results, sends them to my API for categorization, and then displays the categorized results above the main search results.  All in about ~20ms right now.  Granted that’s hitting the API on localhost with less data than a production environment will have but I’m going to be keeping a close eye on performance the whole time since the results are taking over the top of the page and any extra latency will be much worse for user experience since the whole layout will shift.  Right now at this speed you hardly even notice the loading delay as the whole page is loading in.  I’m sure there will be more work needed around optimizing the layout shift as the page loads in the future though.&lt;/p&gt;
&lt;p&gt;Undoubtedly there will be some uncategorized results this early in the project before many people are using the extension.  I’ve seeded some categories based on a few lists I’ve found but the internet is a large place and I’m only going to have a tiny slice categorized when Cat Search launches.  So that’s where all the users come in to either drag an uncategorized result into a category that’s already on the page, or create a new category.  All the categories you create will just be for you to start but the idea is that there will be a process looking across many users that have categorized a site the same way and “promote” the category so that everyone sees it.  This will be a manual process to start with while I figure out what the right criteria is for automatic promotion.&lt;/p&gt;
&lt;p&gt;The last feature I worked on before this post was to automatically load the next pages of results.  This will likely be a paid feature since it’s a nice bonus to the core functionality.  I, like you, am lazy and almost never click next page results.  But I know there’s many times where a better answer to what I’m looking for is buried beneath the SEO spam on page 2, 3, 4, etc. and if it was automatically categorized into a category I highly value (like Indie Blogs) I would click on those results much more often than I do now.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cat Search Mockup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1542&quot; height=&quot;948&quot; src=&quot;/_astro/mockup.Cv_XUelv_Z4HTdW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;And finally, I created a design mockup for the UI!  It’s a little rudimentary as far as full designs go, but it’s enough to get me going.  I’m sure you can tell the actual current state look is, well… very programmer art ish.  It’s functional but not pretty, and that’s just because I hadn’t spent much time on visuals since I was still in the process of figuring out what this thing will become and how it will work.  So next up is just snapping my fingers and making it look like the mockup!&lt;/p&gt;
&lt;h2 id=&quot;challenges&quot;&gt;Challenges&lt;a class=&quot;anchor&quot; href=&quot;#challenges&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this chunk of work there certainly were a number of challenging things that took longer than I expected and some open questions to solve later.&lt;/p&gt;
&lt;h3 id=&quot;result-sorting&quot;&gt;Result Sorting&lt;a class=&quot;anchor&quot; href=&quot;#result-sorting&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first was how voting would interact with dragging a result to a certain position in the category list when it comes to sorting the list the next time (or on page reload).  There’s a number of things to sort results by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My category rank (if I’ve previously dragged a result in the list)&lt;/li&gt;
&lt;li&gt;My category votes (using the up and downvote arrows)&lt;/li&gt;
&lt;li&gt;Other people’s votes on the site and domain&lt;/li&gt;
&lt;li&gt;The search result order&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s a lot of info to take into account while also making the user experience simple, make sense, and consistent.  Currently I’m using the following logic which has worked well for me while using it but I’m curious to see if I get feedback on this.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dragging a result into the top 3 of a category counts as an upvote, anything below that counts as a downvote&lt;/li&gt;
&lt;li&gt;Find all the results in a category that don’t have a category rank, then sort by:
&lt;ul&gt;
&lt;li&gt;Combined vote counts for mine and other people’s votes&lt;/li&gt;
&lt;li&gt;Tie break with the search result page rank&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Insert all the results that &lt;em&gt;do&lt;/em&gt; have a category rank into the appropriate place in the list
&lt;ul&gt;
&lt;li&gt;Tie break with the combined vote counts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This logic ensures if you drag a result to a certain position it stays there, and otherwise highly voted on results bubble to the top, and we fall back to the search engine ranking.&lt;/p&gt;
&lt;h3 id=&quot;db--api-design&quot;&gt;DB &amp;#x26; API Design&lt;a class=&quot;anchor&quot; href=&quot;#db--api-design&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For the API design I wanted to make sure all the necessary changes to the DB when a result is moved categories could happen in one transaction both to keep the DB consistent but also remove the complexity from the frontend and make the API calls efficient.  There’s actually quite a number of DB updates that need to happen for a simple drag action:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check to see if the user has already voted for this site so we can calculate the vote changes if it went from an upvote to downvote.&lt;/li&gt;
&lt;li&gt;Upsert the user site data with the votes&lt;/li&gt;
&lt;li&gt;Upsert the shared category data with the vote changes&lt;/li&gt;
&lt;li&gt;If we’re not categorizing the whole domain, also make sure to upsert the shared &lt;em&gt;domain&lt;/em&gt; category data with the vote changes&lt;/li&gt;
&lt;li&gt;Upsert the user category data with the new category and category rank data&lt;/li&gt;
&lt;li&gt;If the user is moving the result (vs copying), delete the old user category record&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Figuring out the table shapes and API actions for all the combinations of (new || update), (site || whole domain), and (move || copy) definitely took some time to figure out and required some notebook work to help break it down.&lt;/p&gt;
&lt;h3 id=&quot;urls&quot;&gt;URL’s&lt;a class=&quot;anchor&quot; href=&quot;#urls&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Currently my URL matching is limited to either a domain (including the subdomains) or the URL and path (excluding any query parameters).  I’d like to be able to support matching partial URL’s with wild cards for cases where you want to categorize something like a whole subreddit &lt;code&gt;https://reddit.com/r/pics/*&lt;/code&gt;.  This would also allow me to seed more category data based on existing &lt;a href=&quot;https://iorate.github.io/ublacklist/subscriptions?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ublacklist subscriptions&lt;/a&gt;.  Those lists are all full regular expressions though and that sounds way too slow to allow when querying and opens up a whole can of worms.  But for now I’m going to kick that can down the road to post MVP anyways.&lt;/p&gt;
&lt;h2 id=&quot;whats-the-bare-minimum-to-ship&quot;&gt;What’s The Bare Minimum to Ship?&lt;a class=&quot;anchor&quot; href=&quot;#whats-the-bare-minimum-to-ship&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Back to the thought experiment in the title I hope you’ve been thinking about as you read through all the updates though. What constitutes an MVP? How minimalistic do you really need to go? What differentiates a “product” from a demo or a toy?&lt;/p&gt;
&lt;p&gt;There’s a case to be made for rushing to deploy your app as soon as possible and get folks in the door with only the roughest functionality.  That doesn’t sit right with me though for a couple reasons.  You’re giving the people that care about your product the most the worst possible user experience which will inevitably taint their first impression of the product no matter how excited they are for it.  People can only look past so many bugs before they look for alternatives.  If you’ve really shipped as soon as possible that also means you don’t have any way to monitor issues or receive feedback, both of which are absolutely critical for molding software into a delightful user experience that solves a real problem.&lt;/p&gt;
&lt;p&gt;This is one of the lessons I learned from creating Macrocosm.  &lt;strong&gt;You only get one shot at launching.&lt;/strong&gt; Make it count.&lt;/p&gt;
&lt;p&gt;So in my mind the bare minimum things you need before you ship any product are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The core functionality that solves a user problem&lt;/li&gt;
&lt;li&gt;A way to collect user feedback&lt;/li&gt;
&lt;li&gt;A way to monitor problems and usage&lt;/li&gt;
&lt;li&gt;Some form, even if rudimentary, of protecting against abuse&lt;/li&gt;
&lt;li&gt;A way for people to discover and learn about the product&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The big things left on my list I want to tackle before I think it’s &lt;em&gt;really&lt;/em&gt; minimally viable are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implementing the new design&lt;/li&gt;
&lt;li&gt;Proper authentication (I want to allow anonymous usage for a little while to give people the best onboarding experience to try it out, but then require a login to prevent abuse)&lt;/li&gt;
&lt;li&gt;Recording logging for FE &amp;#x26; BE, and telemetry for API response times&lt;/li&gt;
&lt;li&gt;Actually deploying the API (I want to find benchmarks for different cloud providers or run a load test myself to see what gives the best latency)&lt;/li&gt;
&lt;li&gt;Setting up marketing site with info and links&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may or may not notice that paid features aren’t on that list.  This isn’t a charity app and I will have some forms of monetization built in but after debating myself for a bit I decided to have this be the first feature post MVP.  Getting the first few people using the extension, starting to categorize the web, and making sure it’s working well are all more important things than the pro features to start with.&lt;/p&gt;
&lt;p&gt;Hopefully I’ll have at least one more update for you before I get there!&lt;/p&gt;</content:encoded></item><item><title>Collioure, France</title><link>https://dillonshook.com/photos/collioure-france/</link><guid isPermaLink="true">https://dillonshook.com/photos/collioure-france/</guid><description>One of the most scenic towns I&apos;ve ever seen</description><pubDate>Thu, 26 Jun 2025 11:36:12 GMT</pubDate><content:encoded>&lt;h1 id=&quot;-monastery-of-sant-pere-de-rodes&quot;&gt;&lt;svg width=&quot;0.75em&quot; height=&quot;1em&quot; class=&quot;inline&quot; data-icon=&quot;fa6-solid:location-dot&quot;&gt;   &lt;symbol id=&quot;ai:fa6-solid:location-dot&quot; viewBox=&quot;0 0 384 512&quot;&gt;&lt;path fill=&quot;currentColor&quot; d=&quot;M215.7 499.2C267 435 384 279.4 384 192C384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2c12.3 15.3 35.1 15.3 47.4 0M192 128a64 64 0 1 1 0 128a64 64 0 1 1 0-128&quot;/&gt;&lt;/symbol&gt;&lt;use href=&quot;#ai:fa6-solid:location-dot&quot;&gt;&lt;/use&gt;  &lt;/svg&gt; Monastery of Sant Pere de Rodes&lt;a class=&quot;anchor&quot; href=&quot;#-monastery-of-sant-pere-de-rodes&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Our journey to Collioure actually started by going the opposite direction to see the &lt;a href=&quot;https://patrimoni.gencat.cat/en/monuments/monuments/sant-pere-de-rodes-monumental-complex?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Monastery of Sant Pere de Rodes&lt;/a&gt; in the mountains to the east of Peralada where we stayed the night before.  Not sure what was happening here on the way up the mountain but the smoke was gone by the time we came back down the mountain.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940491/collioure-france/DSC03607.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940491/collioure-france/DSC03607.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg&quot; alt=&quot;Spectacular views from the road up&quot; title=&quot;Spectacular views from the road up&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751941347/collioure-france/DSC03612-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg&quot; alt=&quot;And fun roads to drive a stick shift on&quot; title=&quot;And fun roads to drive a stick shift on&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940495/collioure-france/DSC03613-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940497/collioure-france/DSC03614.jpg&quot; alt=&quot;Windy roads&quot; title=&quot;Windy roads&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940497/collioure-france/DSC03614.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940500/collioure-france/DSC03620.jpg&quot; alt=&quot;Our first view of the Monastery&quot; title=&quot;Our first view of the Monastery&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940500/collioure-france/DSC03620.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940502/collioure-france/DSC03627.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940502/collioure-france/DSC03627.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940505/collioure-france/DSC03631.jpg&quot; alt=&quot;Entrance down to the main room&quot; title=&quot;Entrance down to the main room&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940505/collioure-france/DSC03631.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg&quot; alt=&quot;Courtyard towers&quot; title=&quot;Courtyard towers&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940507/collioure-france/DSC03632-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940509/collioure-france/DSC03634.jpg&quot; alt=&quot;Chapel with impressive ceilings for the 11th century&quot; title=&quot;Chapel with impressive ceilings for the 11th century&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940509/collioure-france/DSC03634.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg&quot; alt=&quot;Interior courtyard&quot; title=&quot;Interior courtyard&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940512/collioure-france/DSC03645-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940514/collioure-france/DSC03648.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940514/collioure-france/DSC03648.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940517/collioure-france/DSC03657.jpg&quot; alt=&quot;Bell tower interior&quot; title=&quot;Bell tower interior&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940517/collioure-france/DSC03657.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940519/collioure-france/DSC03665.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940519/collioure-france/DSC03665.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;h1 id=&quot;-collioure-france&quot;&gt;&lt;svg width=&quot;0.75em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 384 512&quot; class=&quot;inline&quot; data-icon=&quot;fa6-solid:location-dot&quot;&gt;   &lt;use href=&quot;#ai:fa6-solid:location-dot&quot;&gt;&lt;/use&gt;  &lt;/svg&gt; Collioure, France&lt;a class=&quot;anchor&quot; href=&quot;#-collioure-france&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;An hour-ish drive and some extremely tight parking later we were ready to be back on foot and explore.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940524/collioure-france/DSC03674.jpg&quot; alt=&quot;There&apos;s so many art shops&quot; title=&quot;There&apos;s so many art shops&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940524/collioure-france/DSC03674.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940526/collioure-france/DSC03690.jpg&quot; alt=&quot;View of the harbor&quot; title=&quot;View of the harbor&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940526/collioure-france/DSC03690.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940529/collioure-france/DSC03693.jpg&quot; alt=&quot;First view of the tower and beach&quot; title=&quot;First view of the tower and beach&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940529/collioure-france/DSC03693.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940532/collioure-france/DSC03703.jpg&quot; alt=&quot;Collioure shops 1&quot; title=&quot;Collioure shops 1&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940532/collioure-france/DSC03703.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940534/collioure-france/DSC03705.jpg&quot; alt=&quot;Collioure shops 2&quot; title=&quot;Collioure shops 2&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940534/collioure-france/DSC03705.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940537/collioure-france/DSC03706.jpg&quot; alt=&quot;Collioure shops 3&quot; title=&quot;Collioure shops 3&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940537/collioure-france/DSC03706.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The tourist train that goes up into the hills outside of town is well worth it for the views even if you can’t understand anything the driver is telling you about what you’re seeing.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940539/collioure-france/DSC03714.jpg&quot; alt=&quot;Tourist train we took that goes up into the hills&quot; title=&quot;Tourist train we took that goes up into the hills&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940539/collioure-france/DSC03714.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940542/collioure-france/DSC03726.jpg&quot; alt=&quot;I&apos;m glad I&apos;m not driving&quot; title=&quot;I&apos;m glad I&apos;m not driving&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940542/collioure-france/DSC03726.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940544/collioure-france/DSC03740.jpg&quot; alt=&quot;Wine has been grown here for many centuries&quot; title=&quot;Wine has been grown here for many centuries&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940544/collioure-france/DSC03740.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940547/collioure-france/DSC03747.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940547/collioure-france/DSC03747.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940550/collioure-france/DSC03756.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940550/collioure-france/DSC03756.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940552/collioure-france/DSC03760.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940552/collioure-france/DSC03760.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940555/collioure-france/DSC03761.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940555/collioure-france/DSC03761.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940558/collioure-france/DSC03773.jpg&quot; alt=&quot;Rolling hills make for good wine&quot; title=&quot;Rolling hills make for good wine&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940558/collioure-france/DSC03773.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg&quot; alt=&quot;Collioure overlook&quot; title=&quot;Collioure overlook&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940560/collioure-france/DSC03794-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940563/collioure-france/DSC03809.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940563/collioure-france/DSC03809.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg&quot; alt=&quot;Surprised to see century plant up here&quot; title=&quot;Surprised to see century plant up here&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940566/collioure-france/DSC03811-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940568/collioure-france/DSC03829.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940568/collioure-france/DSC03829.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940571/collioure-france/DSC03855.jpg&quot; alt=&quot;Alley to get to our stay&quot; title=&quot;Alley to get to our stay&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940571/collioure-france/DSC03855.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940574/collioure-france/DSC03857.jpg&quot; alt=&quot;Sailboats without wind&quot; title=&quot;Sailboats without wind&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940574/collioure-france/DSC03857.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940577/collioure-france/DSC03877.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940577/collioure-france/DSC03877.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940580/collioure-france/DSC03878.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940580/collioure-france/DSC03878.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940582/collioure-france/DSC03882.jpg&quot; alt=&quot;Even the grocery stores are beautiful&quot; title=&quot;Even the grocery stores are beautiful&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940582/collioure-france/DSC03882.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940585/collioure-france/DSC03902.jpg&quot; alt=&quot;View from the castle&quot; title=&quot;View from the castle&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940585/collioure-france/DSC03902.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg&quot; alt=&quot;Overlook from the castle&quot; title=&quot;Overlook from the castle&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940588/collioure-france/DSC03910-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg&quot; alt=&quot;Clear waters in the bay&quot; title=&quot;Clear waters in the bay&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940591/collioure-france/DSC03924-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940593/collioure-france/DSC03928.jpg&quot; alt=&quot;Where the rocks meet the sea&quot; title=&quot;Where the rocks meet the sea&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940593/collioure-france/DSC03928.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940602/collioure-france/DSC03948.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940602/collioure-france/DSC03948.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940604/collioure-france/DSC03971.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940604/collioure-france/DSC03971.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940607/collioure-france/DSC03974.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940607/collioure-france/DSC03974.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940610/collioure-france/DSC03976.jpg&quot; alt=&quot;Artichoke Appetizer&quot; title=&quot;Artichoke Appetizer&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940610/collioure-france/DSC03976.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940616/collioure-france/DSC03979.jpg&quot; alt=&quot;Creamy dessert&quot; title=&quot;Creamy dessert&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940616/collioure-france/DSC03979.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940613/collioure-france/DSC03977.jpg&quot; alt=&quot;Sunset over the castle at dinner&quot; title=&quot;Sunset over the castle at dinner&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940613/collioure-france/DSC03977.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;On our last non travel day we went up to visit the &lt;a href=&quot;https://levinaigre.com/?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;La Guinelle Vinaigrerie&lt;/a&gt; which makes vinegars from premium wine (versus the bad wine most people make vinegar from) and naturally ferments and ages the vinegar in these barrels and bottles.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940621/collioure-france/DSC04001.jpg&quot; alt=&quot;La Guinelle Vinaigrerie&quot; title=&quot;La Guinelle Vinaigrerie&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940621/collioure-france/DSC04001.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940619/collioure-france/DSC03992.jpg&quot; alt=&quot;Vinegar fermentation and aging&quot; title=&quot;Vinegar fermentation and aging&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940619/collioure-france/DSC03992.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;And then off to Les Clos de Paulilles vineyard for lunch&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940624/collioure-france/DSC04005.jpg&quot; alt=&quot;Les Clos de Paulilles for lunch&quot; title=&quot;Les Clos de Paulilles for lunch&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940624/collioure-france/DSC04005.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And then one more squeeze into the tightest driveway I’ve ever gone through which took a ridiculous amount of maneuvering, backing up, spotting, and pumping the clutch.  Each time it took 15 minutes or more just to park.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940627/collioure-france/DSC04025.jpg&quot; alt=&quot;Tight parking&quot; title=&quot;Tight parking&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940627/collioure-france/DSC04025.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>Barcelona</title><link>https://dillonshook.com/photos/barcelona-spain/</link><guid isPermaLink="true">https://dillonshook.com/photos/barcelona-spain/</guid><description>Art and Architecture</description><pubDate>Sun, 22 Jun 2025 11:35:41 GMT</pubDate><content:encoded>&lt;p&gt;It’s time for our next big adventure, this time to Spain and southern France!  Big adventures are harder these days now with a crazy 17 month old toddler in tow that has her own agenda which involves wiggling and causing chaos. Despite that, I still took a ton of pictures that necessitated breaking the trip into two posts!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg&quot; alt=&quot;In line departing from Boston&quot; title=&quot;In line departing from Boston&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938123/barcelona-spain/DSC03060.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;-barcelona-spain&quot;&gt;&lt;svg width=&quot;0.75em&quot; height=&quot;1em&quot; class=&quot;inline&quot; data-icon=&quot;fa6-solid:location-dot&quot;&gt;   &lt;symbol id=&quot;ai:fa6-solid:location-dot&quot; viewBox=&quot;0 0 384 512&quot;&gt;&lt;path fill=&quot;currentColor&quot; d=&quot;M215.7 499.2C267 435 384 279.4 384 192C384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2c12.3 15.3 35.1 15.3 47.4 0M192 128a64 64 0 1 1 0 128a64 64 0 1 1 0-128&quot;/&gt;&lt;/symbol&gt;&lt;use href=&quot;#ai:fa6-solid:location-dot&quot;&gt;&lt;/use&gt;  &lt;/svg&gt; Barcelona, Spain&lt;a class=&quot;anchor&quot; href=&quot;#-barcelona-spain&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg&quot; alt=&quot;Typical Barcelona block&quot; title=&quot;Typical Barcelona block&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938200/barcelona-spain/DSC03069.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg&quot; alt=&quot;So many interior corridors&quot; title=&quot;So many interior corridors&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938133/barcelona-spain/DSC03066.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg&quot; alt=&quot;Barcelona&apos;s Arc de Triomf&quot; title=&quot;Barcelona&apos;s Arc de Triomf&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938250/barcelona-spain/DSC03077.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938249/barcelona-spain/DSC03072.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938251/barcelona-spain/DSC03081.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938256/barcelona-spain/DSC03111.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938252/barcelona-spain/DSC03087.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg&quot; alt=&quot;Ciutadella Park&quot; title=&quot;Ciutadella Park&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938254/barcelona-spain/DSC03095-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg&quot; alt=&quot;Ciutadella Park detail&quot; title=&quot;Ciutadella Park detail&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938255/barcelona-spain/DSC03102.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg&quot; alt=&quot;Tower through the trees&quot; title=&quot;Tower through the trees&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938257/barcelona-spain/DSC03113.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg&quot; alt=&quot;Sagrada Familia at the Lego store&quot; title=&quot;Sagrada Familia at the Lego store&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938259/barcelona-spain/DSC03116.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg&quot; alt=&quot;Lego Car&quot; title=&quot;Lego Car&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938260/barcelona-spain/DSC03122.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Barcelona is well known for its architecture and Casa Batlló is one of the centerpieces by &lt;a href=&quot;https://en.wikipedia.org/wiki/Antoni_Gaud%C3%AD?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Antoni Gaudí&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg&quot; alt=&quot;Casa Batlló&quot; title=&quot;Casa Batlló&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938261/barcelona-spain/DSC03129.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938262/barcelona-spain/DSC03131.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The next day we went for a stroll on La Rambla and through the gothic quarter like all good tourists do when in Barcelona.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg&quot; alt=&quot;Christopher Columbus Monument&quot; title=&quot;Christopher Columbus Monument&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938263/barcelona-spain/DSC03137.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg&quot; alt=&quot;On La Rambla&quot; title=&quot;On La Rambla&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938264/barcelona-spain/DSC03141.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg&quot; alt=&quot;Palau Güell&quot; title=&quot;Palau Güell&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938266/barcelona-spain/DSC03142.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg&quot; alt=&quot;Palau Güell detail and crazy iron work&quot; title=&quot;Palau Güell detail and crazy iron work&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938268/barcelona-spain/DSC03160.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg&quot; alt=&quot;Palau Güell 2&quot; title=&quot;Palau Güell 2&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938267/barcelona-spain/DSC03155-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938271/barcelona-spain/DSC03168.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg&quot; alt=&quot;Sticker graffiti&quot; title=&quot;Sticker graffiti&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938270/barcelona-spain/DSC03162.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg&quot; alt=&quot;Pooping statues seem to be a thing&quot; title=&quot;Pooping statues seem to be a thing&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938272/barcelona-spain/DSC03175.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938273/barcelona-spain/DSC03177.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938275/barcelona-spain/DSC03180.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg&quot; alt=&quot;Guitars being made&quot; title=&quot;Guitars being made&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938276/barcelona-spain/DSC03185.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg&quot; alt=&quot;Harry Potter spreads far&quot; title=&quot;Harry Potter spreads far&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938278/barcelona-spain/DSC03192.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg&quot; alt=&quot;Peeking through alleys at the Cathedral of Barcelona&quot; title=&quot;Peeking through alleys at the Cathedral of Barcelona&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938279/barcelona-spain/DSC03195.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg&quot; alt=&quot;Cathedral of Barcelona&quot; title=&quot;Cathedral of Barcelona&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938280/barcelona-spain/DSC03204-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg&quot; alt=&quot;Living statue in the heat&quot; title=&quot;Living statue in the heat&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938282/barcelona-spain/DSC03205.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938283/barcelona-spain/DSC03217.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;As a way to escape the mid day heat we went to the White Rabbit, “The Off-Museum of Barcelona” which ended up to be pretty fun and a good place for Quinn to play and get some energy out.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg&quot; alt=&quot;Banksy was here&quot; title=&quot;Banksy was here&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938284/barcelona-spain/DSC03228.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938286/barcelona-spain/DSC03240.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg&quot; alt=&quot;Yours, truly&quot; title=&quot;Yours, truly&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938287/barcelona-spain/DSC03244.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg&quot; alt=&quot;Eggs suspended in water jets&quot; title=&quot;Eggs suspended in water jets&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938289/barcelona-spain/DSC03258.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg&quot; alt=&quot;Mirror rooms with screens&quot; title=&quot;Mirror rooms with screens&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938290/barcelona-spain/DSC03266.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg&quot; alt=&quot;Mirror rooms with screens 2&quot; title=&quot;Mirror rooms with screens 2&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938292/barcelona-spain/DSC03267.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg&quot; alt=&quot;Hand cranked video projector&quot; title=&quot;Hand cranked video projector&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938293/barcelona-spain/DSC03274.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg&quot; alt=&quot;Casa Milà&quot; title=&quot;Casa Milà&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938295/barcelona-spain/DSC03281.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938296/barcelona-spain/DSC03283.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938298/barcelona-spain/DSC03288.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg&quot; alt=&quot;The Nautilus?&quot; title=&quot;The Nautilus?&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938299/barcelona-spain/DSC03291.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Next up was taking a tour of the unmistakable &lt;a href=&quot;https://en.wikipedia.org/wiki/Sagrada_Fam%C3%ADlia?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Sagrada Família&lt;/a&gt;, still not quite done after 143 years of construction.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg&quot; alt=&quot;Walking up to Sagrada Família&quot; title=&quot;Walking up to Sagrada Família&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938300/barcelona-spain/DSC03293.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938303/barcelona-spain/DSC03295-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg&quot; alt=&quot;Incredible details&quot; title=&quot;Incredible details&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938304/barcelona-spain/DSC03299.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg&quot; alt=&quot;Incredible sculpting&quot; title=&quot;Incredible sculpting&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938306/barcelona-spain/DSC03300.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938307/barcelona-spain/DSC03302.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg&quot; alt=&quot;Monumental ceilings&quot; title=&quot;Monumental ceilings&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938309/barcelona-spain/DSC03304.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938310/barcelona-spain/DSC03305.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938312/barcelona-spain/DSC03307.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938313/barcelona-spain/DSC03308.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938317/barcelona-spain/DSC03313.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938315/barcelona-spain/DSC03311.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938318/barcelona-spain/DSC03315.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg&quot; alt=&quot;The church is already in use in the crypt where Gaudí is entombed&quot; title=&quot;The church is already in use in the crypt where Gaudí is entombed&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938320/barcelona-spain/DSC03318.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg&quot; alt=&quot;No door left unadorned&quot; title=&quot;No door left unadorned&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938321/barcelona-spain/DSC03319.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg&quot; alt=&quot;Panoramic views of Barcelona from the towers&quot; title=&quot;Panoramic views of Barcelona from the towers&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938324/barcelona-spain/DSC03324-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938325/barcelona-spain/DSC03333.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938327/barcelona-spain/DSC03335.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg&quot; alt=&quot;Park below Sagrada Familia&quot; title=&quot;Park below Sagrada Familia&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938328/barcelona-spain/DSC03336.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938332/barcelona-spain/DSC03347.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938330/barcelona-spain/DSC03340.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938333/barcelona-spain/DSC03352.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg&quot; alt=&quot;Everyone loves the spiral shot&quot; title=&quot;Everyone loves the spiral shot&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938335/barcelona-spain/DSC03362.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938336/barcelona-spain/DSC03376.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;The night before we didn’t sleep all that well since it turned out to be &lt;a href=&quot;https://en.wikipedia.org/wiki/Saint_John%27s_Eve?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Saint John’s Eve&lt;/a&gt; which is &lt;em&gt;enthusiastically&lt;/em&gt; celebrated by setting off fireworks until the wee hours of the morning.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg&quot; alt=&quot;Fireworks aftermath&quot; title=&quot;Fireworks aftermath&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938338/barcelona-spain/DSC03377.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg&quot; alt=&quot;Block of discord&quot; title=&quot;Block of discord&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938341/barcelona-spain/DSC03382-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg&quot; alt=&quot;Casa Amatller&quot; title=&quot;Casa Amatller&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938341/barcelona-spain/DSC03394.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg&quot; alt=&quot;Casa Amatller interior&quot; title=&quot;Casa Amatller interior&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938343/barcelona-spain/DSC03396-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg&quot; alt=&quot;Casa Amatller lights&quot; title=&quot;Casa Amatller lights&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938345/barcelona-spain/DSC03400.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg&quot; alt=&quot;Casa Amatller and Casa Batlló competing&quot; title=&quot;Casa Amatller and Casa Batlló competing&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938347/barcelona-spain/DSC03404-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg&quot; alt=&quot;Lovely little pedestrian only streets&quot; title=&quot;Lovely little pedestrian only streets&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938348/barcelona-spain/DSC03408.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;ul class=&quot;photo-row-flex&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938350/barcelona-spain/DSC03409.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938351/barcelona-spain/DSC03413.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;That evening we took the bus up to Park Güell (pronounced “gway”) which has great views of the city and is one of the places Gaudí lived.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938354/barcelona-spain/DSC03426-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg&quot; alt=&quot;Distant views of the coast&quot; title=&quot;Distant views of the coast&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938355/barcelona-spain/DSC03445.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg&quot; alt=&quot;A floating city arrives&quot; title=&quot;A floating city arrives&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938356/barcelona-spain/DSC03446.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938359/barcelona-spain/DSC03448.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938360/barcelona-spain/DSC03454.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg&quot; alt=&quot;Park Güell main courtyard&quot; title=&quot;Park Güell main courtyard&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751979885/barcelona-spain/DSC03471-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;h1 id=&quot;-catalonia&quot;&gt;&lt;svg width=&quot;0.75em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 384 512&quot; class=&quot;inline&quot; data-icon=&quot;fa6-solid:location-dot&quot;&gt;   &lt;use href=&quot;#ai:fa6-solid:location-dot&quot;&gt;&lt;/use&gt;  &lt;/svg&gt; Catalonia&lt;a class=&quot;anchor&quot; href=&quot;#-catalonia&quot;&gt;&lt;span class=&quot;anchor-icon&quot; data-pagefind-ignore=&quot;true&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;After a couple days it was time to pack back up and get a rental car to see some more of the country.  On the way to our accommodations we stopped at the Clos D’Agon vineyard and winery for a picnic which was nice but pretty hot and sweaty.  We almost had the whole place to ourselves though!&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938362/barcelona-spain/DSC03472.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg&quot; alt=&quot;Clos D&apos;Agon showroom&quot; title=&quot;Clos D&apos;Agon showroom&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938363/barcelona-spain/DSC03474.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg&quot; alt=&quot;Clos D&apos;Agon exterior&quot; title=&quot;Clos D&apos;Agon exterior&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938366/barcelona-spain/DSC03485.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;For the night we splurged on the wonderful &lt;a href=&quot;https://www.hotelperalada.com/en?ref=dillonshook.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hotel Peralada&lt;/a&gt; for our anniversary which has such beautiful grounds, refreshing pool, delicious restaurant, and wine spa which we sadly did not get to try.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg&quot; alt=&quot;Hotel Peralada view from our room&quot; title=&quot;Hotel Peralada view from our room&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938367/barcelona-spain/DSC03490.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg&quot; alt=&quot;Lobby&quot; title=&quot;Lobby&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938369/barcelona-spain/DSC03493.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg&quot; alt=&quot;Poolside bar&quot; title=&quot;Poolside bar&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938370/barcelona-spain/DSC03495.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg&quot; alt=&quot;Hotel Peralada pool&quot; title=&quot;Hotel Peralada pool&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751940440/barcelona-spain/DSC03499-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg&quot; alt=&quot;Ancient olive trees&quot; title=&quot;Ancient olive trees&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938373/barcelona-spain/DSC03501.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg&quot; alt=&quot;Ancient olive trees&quot; title=&quot;Ancient olive trees&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938374/barcelona-spain/DSC03505.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg&quot; alt=&quot;Golf course&quot; title=&quot;Golf course&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938375/barcelona-spain/DSC03510-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg&quot; alt=&quot;Courtyard&quot; title=&quot;Courtyard&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938377/barcelona-spain/DSC03511.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg&quot; alt=&quot;Old olives&quot; title=&quot;Old olives&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938379/barcelona-spain/DSC03527-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938380/barcelona-spain/DSC03536.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938382/barcelona-spain/DSC03540.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 50vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg&quot; alt=&quot;Lovely sunset with dinner&quot; title=&quot;Lovely sunset with dinner&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938384/barcelona-spain/DSC03554-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;The next morning we started with a short drive to visit the Salvador Dalí Museum in Figueres.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938385/barcelona-spain/DSC03563.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938387/barcelona-spain/DSC03566.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938388/barcelona-spain/DSC03569.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg&quot; alt=&quot;Under the dome&quot; title=&quot;Under the dome&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938390/barcelona-spain/DSC03570-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg&quot; alt=&quot;Main atrium&quot; title=&quot;Main atrium&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938391/barcelona-spain/DSC03576.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg&quot; alt=&quot;As viewed from a specially placed lens&quot; title=&quot;As viewed from a specially placed lens&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938393/barcelona-spain/DSC03579.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg&quot; alt=&quot;Outside courtyard&quot; title=&quot;Outside courtyard&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938394/barcelona-spain/DSC03583.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938397/barcelona-spain/DSC03586.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And then it was off to lunch!&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938398/barcelona-spain/DSC03598.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1751938122/barcelona-spain/DSC03604.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;Continue the adventure in part 2, where we make our way up to &lt;a href=&quot;/photos/collioure-france&quot;&gt;Collioure, France!&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Midnight Ride</title><link>https://dillonshook.com/photos/midnight-ride/</link><guid isPermaLink="true">https://dillonshook.com/photos/midnight-ride/</guid><description>Like Paul Revere, except completely different</description><pubDate>Mon, 21 Apr 2025 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Apparently there’s an annual tradition 15 years strong to bike the Boston Marathon route the midnight before it begins.  I heard about this tradition roughly 12 hours before it started from some friends who were going to do it and decided to try it out on a whim despite not having ridden a bike at all in like 2 years, and never having ridden more than a couple miles.&lt;/p&gt;
&lt;p&gt;So on this steel horse I ride, but this one is slow and requires lots of pedaling.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03050.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I did take a peek at the course map beforehand and was relieved to see it’s mostly downhill except for the hills starting at mile 16. Spoiler alert, those were a lot worse in person than they looked on the map.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745456111/midnight-ride/map.png&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745456111/midnight-ride/map.png 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745456111/midnight-ride/map.png 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745456111/midnight-ride/map.png 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745456111/midnight-ride/map.png 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745456111/midnight-ride/map.png 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745456111/midnight-ride/map.png 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Arriving at the start line there were tons of people having fun and preparing their bikes.  There were lots of fun lighting setups from the people who actually prepared for this.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg&quot; alt=&quot;Midnight juggling&quot; title=&quot;Midnight juggling&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02971.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg&quot; alt=&quot;Midnight juggling 2&quot; title=&quot;Midnight juggling 2&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02999.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454871/midnight-ride/DSC02992.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 33vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03020.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 33vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03021.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 33vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03000.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03010.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg&quot; alt=&quot;This cool bike somehow folded down to get off&quot; title=&quot;This cool bike somehow folded down to get off&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454872/midnight-ride/DSC03016.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg&quot; alt=&quot;Laser bike guides&quot; title=&quot;Laser bike guides&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454873/midnight-ride/DSC03022.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg&quot; alt=&quot;Cheating e-bikes ;)&quot; title=&quot;Cheating e-bikes ;)&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454873/midnight-ride/DSC03024.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;I didn’t take as many photos during the ride as I would have liked.  It was hard to justify stopping more than needed when you’re getting constantly passed by other bikers and feeling like this is going to take all night.  We did stop a number of times though to take a break and got a couple shots.&lt;/p&gt;
&lt;div&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg&quot; alt=&quot;Bikers passing the church in Natick&quot; title=&quot;Bikers passing the church in Natick&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454874/midnight-ride/DSC03031.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;photo-row&quot;&gt;&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg&quot; alt=&quot;Boston College&quot; title=&quot;Boston College&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454874/midnight-ride/DSC03035-Pano.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;Around 3am we finally made it to the finish line with sore legs and even sore-r butts but huge smiles on our faces.  You’ll have to ask me for that picture though with how many AI crawlers there are now-days.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg&quot; alt=&quot;Boston Marathon finish line&quot; title=&quot;Boston Marathon finish line&quot; srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03039.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Newbury street is usually packed to the brim, but at this time it’s just bikers trying to get home.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;img src=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_800,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg&quot; alt title srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 1200w&quot; data-pswp-srcset=&quot;https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_600,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 600w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1000,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 1000w,
          https://res.cloudinary.com/dillonshook/image/upload/f_auto,q_95,c_scale,w_1800,dpr_auto/v1745454875/midnight-ride/DSC03047.jpg 1200w&quot; data-pswp-width=&quot;1800&quot; data-pswp-height=&quot;1800&quot; sizes=&quot;(max-width: 720px) 100vw, 100vw&quot; loading=&quot;lazy&quot; class=&quot;post-image&quot;/&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item></channel></rss>